diff options
author | Danny Sonnenschein <my.card.god@web.de> | 2020-10-02 18:52:47 +0300 |
---|---|---|
committer | Antoine du Hamel <duhamelantoine1995@gmail.com> | 2020-10-16 11:21:32 +0300 |
commit | 6f34498148612e8aa3537a9c865d2940cb9e8c7a (patch) | |
tree | 1f93a3db3eada776a79f58741a4d831f8d002376 /src/cares_wrap.cc | |
parent | cfbbeea4a1de41f026b6459d7a680a367addbbb0 (diff) |
net: add support for resolving DNS CAA records
This adds support for DNS Certification Authority Authorization
(RFC 8659) to Node.js.
PR-URL: https://github.com/nodejs/node/pull/35466
Fixes: https://github.com/nodejs/node/issues/19239
Refs: https://github.com/nodejs/node/issues/14713
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'src/cares_wrap.cc')
-rw-r--r-- | src/cares_wrap.cc | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index cc7ad316d2b..fcffc2bec67 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -50,6 +50,10 @@ # include <arpa/nameser.h> #endif +#ifndef T_CAA +# define T_CAA 257 /* Certification Authority Authorization */ +#endif + #if defined(__OpenBSD__) # define AI_V4MAPPED 0 #endif @@ -882,6 +886,43 @@ int ParseMxReply(Environment* env, return ARES_SUCCESS; } +int ParseCaaReply(Environment* env, + const unsigned char* buf, + int len, + Local<Array> ret, + bool need_type = false) { + HandleScope handle_scope(env->isolate()); + auto context = env->context(); + + struct ares_caa_reply* caa_start; + int status = ares_parse_caa_reply(buf, len, &caa_start); + if (status != ARES_SUCCESS) { + return status; + } + + uint32_t offset = ret->Length(); + ares_caa_reply* current = caa_start; + for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { + Local<Object> caa_record = Object::New(env->isolate()); + + caa_record->Set(context, + env->dns_critical_string(), + Integer::New(env->isolate(), current->critical)).Check(); + caa_record->Set(context, + OneByteString(env->isolate(), current->property), + OneByteString(env->isolate(), current->value)).Check(); + if (need_type) + caa_record->Set(context, + env->type_string(), + env->dns_caa_string()).Check(); + + ret->Set(context, i + offset, caa_record).Check(); + } + + ares_free_data(caa_start); + return ARES_SUCCESS; +} + int ParseTxtReply(Environment* env, const unsigned char* buf, int len, @@ -1345,6 +1386,13 @@ class QueryAnyWrap: public QueryWrap { if (!soa_record.IsEmpty()) ret->Set(context, ret->Length(), soa_record).Check(); + /* Parse CAA records */ + status = ParseCaaReply(env(), buf, len, ret, true); + if (status != ARES_SUCCESS && status != ARES_ENODATA) { + ParseError(status); + return; + } + CallOnComplete(ret); } }; @@ -1441,6 +1489,36 @@ class QueryAaaaWrap: public QueryWrap { } }; +class QueryCaaWrap: public QueryWrap { + public: + QueryCaaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj) + : QueryWrap(channel, req_wrap_obj, "resolve6") { + } + + int Send(const char* name) override { + AresQuery(name, ns_c_in, T_CAA); + return 0; + } + + SET_NO_MEMORY_INFO() + SET_MEMORY_INFO_NAME(QueryAaaaWrap) + SET_SELF_SIZE(QueryAaaaWrap) + + protected: + void Parse(unsigned char* buf, int len) override { + HandleScope handle_scope(env()->isolate()); + Context::Scope context_scope(env()->context()); + + Local<Array> ret = Array::New(env()->isolate()); + int status = ParseCaaReply(env(), buf, len, ret); + if (status != ARES_SUCCESS) { + ParseError(status); + return; + } + + this->CallOnComplete(ret); + } +}; class QueryCnameWrap: public QueryWrap { public: @@ -2238,6 +2316,7 @@ void Initialize(Local<Object> target, env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>); env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>); env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>); + env->SetProtoMethod(channel_wrap, "queryCaa", Query<QueryCaaWrap>); env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>); env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>); env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>); |