Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a function to parse a srv reply with ttl #393

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
7a26cb6
add a function to parse a srv reply with ttl
kylebevans Jan 25, 2021
4c9f2b6
remove print statements
kylebevans Jan 25, 2021
ab66778
make ares_parse_srv_reply a wrapper for cares_parse_srv_reply
kylebevans Jan 30, 2021
73d8bf5
return const char* from cares_srv_reply_get_host
kylebevans Jan 30, 2021
eb34dbe
use ares_strdup in ares_parse_srv_reply to copy host string
kylebevans Jan 31, 2021
a86be7e
add new structs and parse functions to support TTL for these RRs:
kylebevans Mar 10, 2021
ce230f7
check hostent->h_addr_list[0] before free
kylebevans Mar 10, 2021
7078113
Merge branch 'master' into kylebevans-ttl
kylebevans Mar 10, 2021
3d06d06
fix loop off by one for freeing h_aliases
kylebevans Mar 10, 2021
a6c585c
modify ptr parsing to use the last hostname as h_name
kylebevans Mar 11, 2021
b55ccb9
use ptr_curr instead of ptr_out to get h_name
kylebevans Mar 11, 2021
08de712
fix memory leaks
kylebevans Mar 13, 2021
7eae6d8
remove debug prints and fix unrelated Container test leak
kylebevans Mar 13, 2021
a82fed6
Merge branch 'main' into kylebevans-ttl
kylebevans Nov 7, 2021
3179732
406 - Validate hostnames in DNS responses
kylebevans Nov 7, 2021
1e03b81
fix a missed a conflict in ares.h
kylebevans Nov 7, 2021
d36bec7
add is_hostname parameter back in one spot
kylebevans Nov 7, 2021
2814894
change struct cares_ to just cares_ for declarations
kylebevans Nov 7, 2021
7fcb191
change ttl in ares_uri_reply to be unsigned int
kylebevans Nov 7, 2021
487d072
change ARES_DATATYPE_C prefix to CARES_DATATYPE_ prefix
kylebevans Nov 7, 2021
97143cc
return const from cares_get_next functions
kylebevans Nov 12, 2021
699a9cd
create cares_memdup function as sugar for malloc/memcpy pattern
kylebevans Nov 12, 2021
3286a5d
save progress
kylebevans Dec 29, 2021
aed6a71
save progress
kylebevans Dec 29, 2021
baf30b8
save progress
kylebevans Dec 30, 2021
6983bc3
add free routine for container
kylebevans Dec 30, 2021
39c8e55
add malloc routine for container
kylebevans Dec 31, 2021
385a3fe
change cares_parse_srv_reply to use container
kylebevans Dec 31, 2021
697b9fd
change ares_parse_srv_reply to use container
kylebevans Dec 31, 2021
de092f3
fix errors and warnings
kylebevans Dec 31, 2021
9583762
fix errors and warnings
kylebevans Dec 31, 2021
e22efd5
add debugging
kylebevans Jan 1, 2022
f349105
fix crashes and add debugging
kylebevans Jan 2, 2022
867e3f7
fix crashes
kylebevans Jan 2, 2022
0f5ba50
remove print statements
kylebevans Jan 2, 2022
9268be0
Add build/test instructions for asan
kylebevans Jan 2, 2022
13aec44
update build/test instructions for asan
kylebevans Jan 2, 2022
86daca3
update build/test instructions for asan
kylebevans Jan 2, 2022
9f7b8b9
update build/test instructions for asan
kylebevans Jan 2, 2022
487cb0c
attempt to fix leak
kylebevans Jan 2, 2022
84d87cb
attempt to fix leak
kylebevans Jan 2, 2022
f131cf2
add missing break statement
kylebevans Jan 2, 2022
8bca0fa
free srv_host on error
kylebevans Jan 2, 2022
979f715
add debugging
kylebevans Jan 2, 2022
183a999
fix leak if no srv rr type
kylebevans Jan 3, 2022
e247b6e
add fuzzing loop instrution
kylebevans Jan 3, 2022
e1bb47d
fix typo for cares_free_container.h
kylebevans Jan 3, 2022
73248f7
remove debugging print statements
kylebevans Jan 3, 2022
337db1d
Update instructions for lsan
kylebevans Jan 4, 2022
be37e6a
Update instructions for lsan
kylebevans Jan 4, 2022
e82ff03
change srv to csrv
kylebevans Jan 4, 2022
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ CHANGES.dist
c-ares-*.tar.gz.asc
ares_parse_mx_reply.pdf
/[0-9]*.patch
.dirstamp
54 changes: 48 additions & 6 deletions include/ares.h
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,10 @@ struct ares_srv_reply {
unsigned short port;
};

struct cares_srv_reply;

typedef struct cares_srv_reply cares_srv_reply;

struct ares_mx_reply {
struct ares_mx_reply *next;
char *host;
Expand Down Expand Up @@ -647,8 +651,8 @@ CARES_EXTERN int ares_parse_aaaa_reply(const unsigned char *abuf,
int *naddrttls);

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

CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf,
int alen,
Expand All @@ -665,9 +669,47 @@ CARES_EXTERN int ares_parse_srv_reply(const unsigned char* abuf,
int alen,
struct ares_srv_reply** srv_out);

CARES_EXTERN int cares_parse_srv_reply(const unsigned char* abuf,
int alen,
struct cares_srv_reply** srv_out);

CARES_EXTERN struct cares_srv_reply*
cares_srv_reply_get_next(const cares_srv_reply* srv_reply);

CARES_EXTERN char* cares_srv_reply_get_host(const cares_srv_reply* srv_reply);

CARES_EXTERN unsigned short
cares_srv_reply_get_priority(const cares_srv_reply* srv_reply);

CARES_EXTERN unsigned short
cares_srv_reply_get_weight(const cares_srv_reply* srv_reply);

CARES_EXTERN unsigned short
cares_srv_reply_get_port(const cares_srv_reply* srv_reply);

CARES_EXTERN int cares_srv_reply_get_ttl(const cares_srv_reply* srv_reply);

CARES_EXTERN void cares_srv_reply_set_next(cares_srv_reply* srv_reply,
struct cares_srv_reply* next);

CARES_EXTERN void
cares_srv_reply_set_host(cares_srv_reply* srv_reply, char* host);

CARES_EXTERN void cares_srv_reply_set_priority(cares_srv_reply* srv_reply,
const unsigned short priority);

CARES_EXTERN void cares_srv_reply_set_weight(cares_srv_reply* srv_reply,
const unsigned short weight);

CARES_EXTERN void cares_srv_reply_set_port(cares_srv_reply* srv_reply,
const unsigned short port);

CARES_EXTERN void cares_srv_reply_set_ttl(cares_srv_reply* srv_reply,
const int ttl);

CARES_EXTERN int ares_parse_mx_reply(const unsigned char* abuf,
int alen,
struct ares_mx_reply** mx_out);
int alen,
struct ares_mx_reply** mx_out);

CARES_EXTERN int ares_parse_txt_reply(const unsigned char* abuf,
int alen,
Expand All @@ -682,8 +724,8 @@ CARES_EXTERN int ares_parse_naptr_reply(const unsigned char* abuf,
struct ares_naptr_reply** naptr_out);

CARES_EXTERN int ares_parse_soa_reply(const unsigned char* abuf,
int alen,
struct ares_soa_reply** soa_out);
int alen,
struct ares_soa_reply** soa_out);

CARES_EXTERN void ares_free_string(void *str);

Expand Down
2 changes: 2 additions & 0 deletions src/lib/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ CSOURCES = ares__close_sockets.c \
ares_parse_ptr_reply.c \
ares_parse_soa_reply.c \
ares_parse_srv_reply.c \
cares_parse_srv_reply.c \
ares_parse_txt_reply.c \
ares_platform.c \
ares_process.c \
ares_query.c \
cares_reply.c \
ares_search.c \
ares_send.c \
ares_strcasecmp.c \
Expand Down
8 changes: 7 additions & 1 deletion src/lib/ares_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
** function is:
**
** ares_get_servers()
** cares_parse_srv_reply()
** ares_parse_srv_reply()
** ares_parse_txt_reply()
*/
Expand Down Expand Up @@ -70,6 +71,7 @@ void ares_free_data(void *dataptr)
break;

case ARES_DATATYPE_SRV_REPLY:
case ARES_DATATYPE_CSRV_REPLY:

if (ptr->data.srv_reply.next)
next_data = ptr->data.srv_reply.next;
Expand Down Expand Up @@ -120,7 +122,7 @@ void ares_free_data(void *dataptr)
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)
Expand Down Expand Up @@ -166,6 +168,10 @@ void *ares_malloc_data(ares_datatype type)
ptr->data.mx_reply.priority = 0;
break;

case ARES_DATATYPE_CSRV_REPLY:
ptr->data.csrv_reply.ttl = 0;
/* FALLTHROUGH */

case ARES_DATATYPE_SRV_REPLY:
ptr->data.srv_reply.next = NULL;
ptr->data.srv_reply.host = NULL;
Expand Down
3 changes: 3 additions & 0 deletions src/lib/ares_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
* without express or implied warranty.
*/

#include "ares_private.h"
typedef enum {
ARES_DATATYPE_UNKNOWN = 1, /* unknown data type - introduced in 1.7.0 */
ARES_DATATYPE_SRV_REPLY, /* struct ares_srv_reply - introduced in 1.7.0 */
ARES_DATATYPE_CSRV_REPLY, /* struct cares_srv_reply */
ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply - introduced in 1.7.0 */
ARES_DATATYPE_TXT_EXT, /* struct ares_txt_ext - introduced in 1.11.0 */
ARES_DATATYPE_ADDR_NODE, /* struct ares_addr_node - introduced in 1.7.1 */
Expand Down Expand Up @@ -61,6 +63,7 @@ struct ares_data {
struct ares_txt_reply txt_reply;
struct ares_txt_ext txt_ext;
struct ares_srv_reply srv_reply;
struct cares_srv_reply csrv_reply;
struct ares_addr_node addr_node;
struct ares_addr_port_node addr_port_node;
struct ares_mx_reply mx_reply;
Expand Down
159 changes: 52 additions & 107 deletions src/lib/ares_parse_srv_reply.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,128 +38,73 @@ int
ares_parse_srv_reply (const unsigned char *abuf, int alen,
struct ares_srv_reply **srv_out)
{
unsigned int qdcount, ancount, i;
const unsigned char *aptr, *vptr;
int status, rr_type, rr_class, rr_len;
long len;
char *hostname = NULL, *rr_name = NULL;

/* call cares_parse_srv_reply, iterate through the result and
* create a linked list of struct ares_srv_reply to return */

int status;
struct ares_srv_reply *srv_head = NULL;
struct ares_srv_reply *srv_curr = NULL;
struct ares_srv_reply *srv_last = NULL;
struct ares_srv_reply *srv_curr;
struct cares_srv_reply *csrv_curr = NULL;
struct cares_srv_reply *csrv_out = NULL;

/* Set *srv_out to NULL for all failure cases. */
*srv_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);
status = cares_parse_srv_reply(abuf, alen, &csrv_out);

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

if (aptr + len + QFIXEDSZ > abuf + alen)
}

/* iterate through the cares_srv_reply list and
* create a new ares_srv_reply */
for (csrv_curr = csrv_out; csrv_curr;
csrv_curr = cares_srv_reply_get_next(csrv_curr))
{
srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY);
if (!srv_curr)
{
ares_free (hostname);
return ARES_EBADRESP;
status = ARES_ENOMEM;
break;
}
aptr += len + QFIXEDSZ;

/* Examine each answer resource record (RR) in turn. */
for (i = 0; i < ancount; i++)
if (srv_last)
{
srv_last->next = srv_curr;
}
else
{
srv_head = srv_curr;
}
srv_last = srv_curr;
srv_curr->host = cares_srv_reply_get_host(csrv_curr);
if (!srv_curr->host)
{
/* 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 SRV record */
if (rr_class == C_IN && rr_type == T_SRV)
{
/* parse the SRV record itself */
if (rr_len < 6)
{
status = ARES_EBADRESP;
break;
}

/* Allocate storage for this SRV answer appending it to the list */
srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY);
if (!srv_curr)
{
status = ARES_ENOMEM;
break;
}
if (srv_last)
{
srv_last->next = srv_curr;
}
else
{
srv_head = srv_curr;
}
srv_last = srv_curr;

vptr = aptr;
srv_curr->priority = DNS__16BIT(vptr);
vptr += sizeof(unsigned short);
srv_curr->weight = DNS__16BIT(vptr);
vptr += sizeof(unsigned short);
srv_curr->port = DNS__16BIT(vptr);
vptr += sizeof(unsigned short);

status = ares_expand_name (vptr, abuf, alen, &srv_curr->host, &len);
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;
status = ARES_ENOMEM;
break;
}
srv_curr->priority = cares_srv_reply_get_priority(csrv_curr);
srv_curr->weight = cares_srv_reply_get_weight(csrv_curr);
srv_curr->port = cares_srv_reply_get_port(csrv_curr);
}

if (hostname)
ares_free (hostname);
if (rr_name)
ares_free (rr_name);
if (csrv_out)
{
ares_free_data (csrv_out);
}

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

/* everything looks fine, return the data */
*srv_out = srv_head;
Expand Down
14 changes: 14 additions & 0 deletions src/lib/ares_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,4 +416,18 @@ int ares__connect_socket(ares_channel channel,
(c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w)); \
} WHILE_FALSE

/* Private definition of c-ares srv reply so that c-ares users
* only have access to the type definition in ares.h and must use
* accessor functions to interact with the struct. This way,
* cares_srv_reply can be modified without breaking ABI.
*/
struct cares_srv_reply {
struct cares_srv_reply *next;
char *host;
unsigned short priority;
unsigned short weight;
unsigned short port;
int ttl;
};

#endif /* __ARES_PRIVATE_H */
Loading