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 1 commit
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
Next Next commit
add a function to parse a srv reply with ttl
This adds a new private srv record struct with a ttl field.
It also adds public accessor functions to set all of the
fields.  Finally, it replicates the ares_parse_srv_reply
function to use the new struct and accessors.
  • Loading branch information
kylebevans committed Jan 25, 2021
commit 7a26cb65c1c2136fe1a2a41636ee95587b91633f
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
37 changes: 37 additions & 0 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 ares_srv_ext;

typedef struct ares_srv_ext ares_srv_ext;

struct ares_mx_reply {
struct ares_mx_reply *next;
char *host;
Expand Down Expand Up @@ -665,6 +669,39 @@ CARES_EXTERN int ares_parse_srv_reply(const unsigned char* abuf,
int alen,
struct ares_srv_reply** srv_out);

CARES_EXTERN int ares_parse_srv_reply_ext(const unsigned char* abuf,
int alen,
struct ares_srv_ext** srv_out);

CARES_EXTERN struct ares_srv_ext* ares_srv_ext_get_next(const ares_srv_ext* srv_reply);

CARES_EXTERN char* ares_srv_ext_get_host(const ares_srv_ext* srv_reply);

CARES_EXTERN unsigned short ares_srv_ext_get_priority(const ares_srv_ext* srv_reply);

CARES_EXTERN unsigned short ares_srv_ext_get_weight(const ares_srv_ext* srv_reply);

CARES_EXTERN unsigned short ares_srv_ext_get_port(const ares_srv_ext* srv_reply);

CARES_EXTERN int ares_srv_ext_get_ttl(const ares_srv_ext* srv_reply);

CARES_EXTERN void ares_srv_ext_set_next(ares_srv_ext* srv_reply,
struct ares_srv_ext* next);

CARES_EXTERN void ares_srv_ext_set_host(ares_srv_ext* srv_reply, char* host);

CARES_EXTERN void ares_srv_ext_set_priority(ares_srv_ext* srv_reply,
const unsigned short priority);

CARES_EXTERN void ares_srv_ext_set_weight(ares_srv_ext* srv_reply,
const unsigned short weight);

CARES_EXTERN void ares_srv_ext_set_port(ares_srv_ext* srv_reply,
const unsigned short port);

CARES_EXTERN void ares_srv_ext_set_ttl(ares_srv_ext* srv_reply,
const int ttl);

CARES_EXTERN int ares_parse_mx_reply(const unsigned char* abuf,
int alen,
struct ares_mx_reply** mx_out);
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 \
ares_parse_srv_reply_ext.c \
ares_parse_txt_reply.c \
ares_platform.c \
ares_process.c \
ares_query.c \
ares_reply_ext.c \
ares_search.c \
ares_send.c \
ares_strcasecmp.c \
Expand Down
7 changes: 6 additions & 1 deletion src/lib/ares_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ void ares_free_data(void *dataptr)
break;

case ARES_DATATYPE_SRV_REPLY:
case ARES_DATATYPE_SRV_EXT:

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

case ARES_DATATYPE_SRV_EXT:
ptr->data.srv_ext.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_SRV_EXT, /* struct ares_srv_ext */
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 ares_srv_ext srv_ext;
struct ares_addr_node addr_node;
struct ares_addr_port_node addr_port_node;
struct ares_mx_reply mx_reply;
Expand Down
173 changes: 173 additions & 0 deletions src/lib/ares_parse_srv_reply_ext.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@

/* Copyright 1998 by the Massachusetts Institute of Technology.
* Copyright (C) 2009 by Jakub Hrozek <jhrozek@redhat.com>
*
* 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

#include "ares_nameser.h"

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

int
ares_parse_srv_reply_ext (const unsigned char *abuf, int alen,
struct ares_srv_ext **srv_out)
{
unsigned int qdcount, ancount, i;
const unsigned char *aptr, *vptr;
int status, rr_type, rr_class, rr_ttl, rr_len;
long len;
char *hostname = NULL, *rr_name = NULL;
struct ares_srv_ext *srv_head = NULL;
struct ares_srv_ext *srv_last = NULL;
struct ares_srv_ext *srv_curr;

/* 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);
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_ttl = DNS_RR_TTL (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_EXT);
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;
ares_srv_ext_set_priority(srv_curr, DNS__16BIT(vptr));
vptr += sizeof(unsigned short);
ares_srv_ext_set_weight(srv_curr, DNS__16BIT(vptr));
vptr += sizeof(unsigned short);
ares_srv_ext_set_port(srv_curr, DNS__16BIT(vptr));
vptr += sizeof(unsigned short);
ares_srv_ext_set_ttl(srv_curr, rr_ttl);

char* srv_host = NULL;

status = ares_expand_name (vptr, abuf, alen, &srv_host, &len);
printf("srv host: %s\n", srv_host);
ares_srv_ext_set_host(srv_curr, srv_host);
printf("srv curr host: %s\n", ares_srv_ext_get_host(srv_curr));
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 (srv_head)
ares_free_data (srv_head);
return status;
}

/* everything looks fine, return the data */
*srv_out = srv_head;
return ARES_SUCCESS;
}
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 extended 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,
* ares_srv_reply_ext can be modified without breaking ABI.
*/
struct ares_srv_ext {
struct ares_srv_ext *next;
char *host;
unsigned short priority;
unsigned short weight;
unsigned short port;
int ttl;
};

#endif /* __ARES_PRIVATE_H */
80 changes: 80 additions & 0 deletions src/lib/ares_reply_ext.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* Copyright (C) 2021 by Kyle Evans
*
* 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"
#include "ares.h"
#include "ares_private.h"

struct ares_srv_ext* ares_srv_ext_get_next(const struct ares_srv_ext* srv_reply)
{
return srv_reply->next;
}

char* ares_srv_ext_get_host(const struct ares_srv_ext* srv_reply)
{
return srv_reply->host;
}

unsigned short ares_srv_ext_get_priority(const struct ares_srv_ext* srv_reply)
{
return srv_reply->priority;
}

unsigned short ares_srv_ext_get_weight(const struct ares_srv_ext* srv_reply)
{
return srv_reply->weight;
}

unsigned short ares_srv_ext_get_port(const struct ares_srv_ext* srv_reply)
{
return srv_reply->port;
}

int ares_srv_ext_get_ttl(const struct ares_srv_ext* srv_reply)
{
return srv_reply->ttl;
}

void ares_srv_ext_set_next(struct ares_srv_ext* srv_reply,
struct ares_srv_ext* next)
{
srv_reply->next = next;
}

void ares_srv_ext_set_host(struct ares_srv_ext* srv_reply, char* host)
{
srv_reply->host = host;
}

void ares_srv_ext_set_priority(struct ares_srv_ext* srv_reply,
const unsigned short priority)
{
srv_reply->priority = priority;
}

void ares_srv_ext_set_weight(struct ares_srv_ext* srv_reply,
const unsigned short weight)
{
srv_reply->weight = weight;
}

void ares_srv_ext_set_port(struct ares_srv_ext* srv_reply,
const unsigned short port)
{
srv_reply->port = port;
}

void ares_srv_ext_set_ttl(struct ares_srv_ext* srv_reply, const int ttl)
{
srv_reply->ttl = ttl;
}
Loading