Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions deps/cares/cares.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
'defines': [
'_DARWIN_USE_64_BIT_INODE=1',
'_LARGEFILE_SOURCE',
'_FILE_OFFSET_BITS=64',
'_GNU_SOURCE'
'_FILE_OFFSET_BITS=64', '_GNU_SOURCE'
Comment thread
lxdicted marked this conversation as resolved.
Outdated
]
}],
[ 'OS=="aix"', {
Expand Down Expand Up @@ -75,6 +74,7 @@
'src/ares__parse_into_addrinfo.c',
'src/ares_parse_aaaa_reply.c',
'src/ares_parse_a_reply.c',
'src/ares_parse_caa_reply.c',
'src/ares_parse_mx_reply.c',
'src/ares_parse_naptr_reply.c',
'src/ares_parse_ns_reply.c',
Expand Down
13 changes: 13 additions & 0 deletions deps/cares/include/ares.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,15 @@ struct ares_addr6ttl {
int ttl;
};

struct ares_caa_reply {
struct ares_caa_reply *next;
int critical;
unsigned char *property;
size_t plength; /* plength excludes null termination */
unsigned char *value;
size_t length; /* length excludes null termination */
};

struct ares_srv_reply {
struct ares_srv_reply *next;
char *host;
Expand Down Expand Up @@ -637,6 +646,10 @@ CARES_EXTERN int ares_parse_aaaa_reply(const unsigned char *abuf,
struct ares_addr6ttl *addrttls,
int *naddrttls);

CARES_EXTERN int ares_parse_caa_reply(const unsigned char* abuf,
int alen,
struct ares_caa_reply** caa_out);

CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf,
int alen,
const void *addr,
Expand Down
18 changes: 18 additions & 0 deletions deps/cares/src/ares_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ void ares_free_data(void *dataptr)
ares_free(ptr->data.soa_reply.hostmaster);
break;

case ARES_DATATYPE_CAA_REPLY:

if (ptr->data.caa_reply.next)
next_data = ptr->data.caa_reply.next;
if (ptr->data.caa_reply.property)
ares_free(ptr->data.caa_reply.property);
if (ptr->data.caa_reply.value)
ares_free(ptr->data.caa_reply.value);
break;

default:
return;
}
Expand Down Expand Up @@ -174,6 +184,14 @@ void *ares_malloc_data(ares_datatype type)
ptr->data.txt_reply.length = 0;
break;

case ARES_DATATYPE_CAA_REPLY:
ptr->data.caa_reply.next = NULL;
ptr->data.caa_reply.plength = 0;
ptr->data.caa_reply.property = NULL;
ptr->data.caa_reply.length = 0;
ptr->data.caa_reply.value = NULL;
break;

case ARES_DATATYPE_ADDR_NODE:
ptr->data.addr_node.next = NULL;
ptr->data.addr_node.family = 0;
Expand Down
2 changes: 2 additions & 0 deletions deps/cares/src/ares_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ typedef enum {
ARES_DATATYPE_OPTIONS, /* struct ares_options */
#endif
ARES_DATATYPE_ADDR_PORT_NODE, /* struct ares_addr_port_node - introduced in 1.11.0 */
ARES_DATATYPE_CAA_REPLY, /* struct ares_caa_reply - introduced in 1.17 */
ARES_DATATYPE_LAST /* not used - introduced in 1.7.0 */
} ares_datatype;

Expand Down Expand Up @@ -65,6 +66,7 @@ struct ares_data {
struct ares_mx_reply mx_reply;
struct ares_naptr_reply naptr_reply;
struct ares_soa_reply soa_reply;
struct ares_caa_reply caa_reply;
} data;
};

Expand Down
209 changes: 209 additions & 0 deletions deps/cares/src/ares_parse_caa_reply.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@

/* Copyright 2020 by <danny.sonnenschein@platynum.ch>
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

#include "ares_setup.h"

#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#else
# include "nameser.h"
#endif
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
# include <arpa/nameser_compat.h>
#endif

#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif

#include "ares.h"
#include "ares_dns.h"
#include "ares_data.h"
#include "ares_private.h"

#ifndef T_CAA
# define T_CAA 257 /* Certification Authority Authorization */
#endif

int
ares_parse_caa_reply (const unsigned char *abuf, int alen,
struct ares_caa_reply **caa_out)
{
unsigned int qdcount, ancount, i;
const unsigned char *aptr;
const unsigned char *strptr;
int status, rr_type, rr_class, rr_len;
long len;
char *hostname = NULL, *rr_name = NULL;
struct ares_caa_reply *caa_head = NULL;
struct ares_caa_reply *caa_last = NULL;
struct ares_caa_reply *caa_curr;

/* Set *caa_out to NULL for all failure cases. */
*caa_out = NULL;

/* Give up if abuf doesn't have room for a header. */
if (alen < HFIXEDSZ)
return ARES_EBADRESP;

/* Fetch the question and answer count from the header. */
qdcount = DNS_HEADER_QDCOUNT (abuf);
ancount = DNS_HEADER_ANCOUNT (abuf);
if (qdcount != 1)
return ARES_EBADRESP;
if (ancount == 0)
return ARES_ENODATA;

/* Expand the name from the question, and skip past the question. */
aptr = abuf + HFIXEDSZ;
status = ares_expand_name (aptr, abuf, alen, &hostname, &len);
if (status != ARES_SUCCESS)
return status;

if (aptr + len + QFIXEDSZ > abuf + alen)
{
ares_free (hostname);
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;

/* Examine each answer resource record (RR) in turn. */
for (i = 0; i < ancount; i++)
{
/* Decode the RR up to the data field. */
status = ares_expand_name (aptr, abuf, alen, &rr_name, &len);
if (status != ARES_SUCCESS)
{
break;
}
aptr += len;
if (aptr + RRFIXEDSZ > abuf + alen)
{
status = ARES_EBADRESP;
break;
}
rr_type = DNS_RR_TYPE (aptr);
rr_class = DNS_RR_CLASS (aptr);
rr_len = DNS_RR_LEN (aptr);
aptr += RRFIXEDSZ;
if (aptr + rr_len > abuf + alen)
{
status = ARES_EBADRESP;
break;
}

/* Check if we are really looking at a CAA record */
if ((rr_class == C_IN || rr_class == C_CHAOS) && rr_type == T_CAA)
{
strptr = aptr;

/* Allocate storage for this CAA answer appending it to the list */
caa_curr = ares_malloc_data(ARES_DATATYPE_CAA_REPLY);
if (!caa_curr)
{
status = ARES_ENOMEM;
break;
}
if (caa_last)
{
caa_last->next = caa_curr;
}
else
{
caa_head = caa_curr;
}
caa_last = caa_curr;
if (rr_len < 2)
{
status = ARES_EBADRESP;
break;
}
caa_curr->critical = (int)*strptr++;
caa_curr->plength = (int)*strptr++;
if (caa_curr->plength <= 0 || (int)caa_curr->plength >= rr_len - 2)
{
status = ARES_EBADRESP;
break;
}
caa_curr->property = ares_malloc (caa_curr->plength + 1/* Including null byte */);
if (caa_curr->property == NULL)
{
status = ARES_ENOMEM;
break;
}
memcpy ((char *) caa_curr->property, strptr, caa_curr->plength);
/* Make sure we NULL-terminate */
caa_curr->property[caa_curr->plength] = 0;
strptr += caa_curr->plength;

caa_curr->length = rr_len - caa_curr->plength - 2;
if (caa_curr->length <= 0)
{
status = ARES_EBADRESP;
break;
}
caa_curr->value = ares_malloc (caa_curr->length + 1/* Including null byte */);
if (caa_curr->value == NULL)
{
status = ARES_ENOMEM;
break;
}
memcpy ((char *) caa_curr->value, strptr, caa_curr->length);
/* Make sure we NULL-terminate */
caa_curr->value[caa_curr->length] = 0;
}

/* Propagate any failures */
if (status != ARES_SUCCESS)
{
break;
}

/* Don't lose memory in the next iteration */
ares_free (rr_name);
rr_name = NULL;

/* Move on to the next record */
aptr += rr_len;
}

if (hostname)
ares_free (hostname);
if (rr_name)
ares_free (rr_name);

/* clean up on error */
if (status != ARES_SUCCESS)
{
if (caa_head)
ares_free_data (caa_head);
return status;
}

/* everything looks fine, return the data */
*caa_out = caa_head;

return ARES_SUCCESS;
}
17 changes: 17 additions & 0 deletions doc/api/dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ The following methods from the `dns` module are available:
* [`resolver.resolve4()`][`dns.resolve4()`]
* [`resolver.resolve6()`][`dns.resolve6()`]
* [`resolver.resolveAny()`][`dns.resolveAny()`]
* [`resolver.resolveCaa()`][`dns.resolveCaa()`]
* [`resolver.resolveCname()`][`dns.resolveCname()`]
* [`resolver.resolveMx()`][`dns.resolveMx()`]
* [`resolver.resolveNaptr()`][`dns.resolveNaptr()`]
Expand Down Expand Up @@ -290,6 +291,7 @@ records. The type and structure of individual results varies based on `rrtype`:
| `'AAAA'` | IPv6 addresses | {string} | [`dns.resolve6()`][] |
| `'ANY'` | any records | {Object} | [`dns.resolveAny()`][] |
| `'CNAME'` | canonical name records | {string} | [`dns.resolveCname()`][] |
| `'CAA'` | CA authorization | {Object} | [`dns.resolveCaa()`][] |
| `'MX'` | mail exchange records | {Object} | [`dns.resolveMx()`][] |
| `'NAPTR'` | name authority pointer records | {Object} | [`dns.resolveNaptr()`][] |
| `'NS'` | name server records | {string} | [`dns.resolveNs()`][] |
Expand Down Expand Up @@ -414,6 +416,21 @@ Uses the DNS protocol to resolve `CNAME` records for the `hostname`. The
will contain an array of canonical name records available for the `hostname`
(e.g. `['bar.example.com']`).

## `dns.resolveCaa(hostname, callback)`
<!-- YAML
added: v0.3.2
Comment thread
lxdicted marked this conversation as resolved.
Outdated
-->

* `hostname` {string}
* `callback` {Function}
* `err` {Error}
* `records` {Object[]}

Uses the DNS protocol to resolve `CAA` records for the `hostname`. The
`addresses` argument passed to the `callback` function
will contain an array of certification authority authorization records
available for the `hostname` (e.g. `[{critial: 0, iodef: 'letsencrypt.org']`).

## `dns.resolveMx(hostname, callback)`
<!-- YAML
added: v0.1.27
Expand Down
1 change: 1 addition & 0 deletions lib/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ const resolveMap = ObjectCreate(null);
Resolver.prototype.resolveAny = resolveMap.ANY = resolver('queryAny');
Resolver.prototype.resolve4 = resolveMap.A = resolver('queryA');
Resolver.prototype.resolve6 = resolveMap.AAAA = resolver('queryAaaa');
Resolver.prototype.resolveCaa = resolveMap.CAA = resolver('queryCaa');
Resolver.prototype.resolveCname = resolveMap.CNAME = resolver('queryCname');
Resolver.prototype.resolveMx = resolveMap.MX = resolver('queryMx');
Resolver.prototype.resolveNs = resolveMap.NS = resolver('queryNs');
Expand Down
1 change: 1 addition & 0 deletions lib/internal/dns/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ Resolver.prototype.setServers = CallbackResolver.prototype.setServers;
Resolver.prototype.resolveAny = resolveMap.ANY = resolver('queryAny');
Resolver.prototype.resolve4 = resolveMap.A = resolver('queryA');
Resolver.prototype.resolve6 = resolveMap.AAAA = resolver('queryAaaa');
Resolver.prototype.resolveCaa = resolveMap.CAA = resolver('queryCaa');
Resolver.prototype.resolveCname = resolveMap.CNAME = resolver('queryCname');
Resolver.prototype.resolveMx = resolveMap.MX = resolver('queryMx');
Resolver.prototype.resolveNs = resolveMap.NS = resolver('queryNs');
Expand Down
1 change: 1 addition & 0 deletions lib/internal/dns/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const resolverKeys = [
'resolve4',
'resolve6',
'resolveAny',
'resolveCaa',
'resolveCname',
'resolveMx',
'resolveNaptr',
Expand Down
Loading