diff --git a/Makefile.in b/Makefile.in index e052d610..472ab2e9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -31,6 +31,9 @@ uninstall: doc: cd doc && $(MAKE) $@ +example: + cd src && $(MAKE) $@ + test: cd src && $(MAKE) $@ diff --git a/src/general.c b/src/general.c index c5c80b31..35dfef13 100644 --- a/src/general.c +++ b/src/general.c @@ -341,6 +341,11 @@ getdns_general(struct getdns_context *context, return GETDNS_RETURN_INVALID_PARAMETER; } + extcheck = validate_dname(name); + if (extcheck != GETDNS_RETURN_GOOD) { + return extcheck; + } + extcheck = validate_extensions(extensions); if (extcheck != GETDNS_RETURN_GOOD) return extcheck; diff --git a/src/sync.c b/src/sync.c index 5519c757..48b0ad84 100644 --- a/src/sync.c +++ b/src/sync.c @@ -71,6 +71,11 @@ getdns_general_sync(struct getdns_context *context, getdns_return_t response_status; RETURN_IF_NULL(context, GETDNS_RETURN_BAD_CONTEXT); RETURN_IF_NULL(response, GETDNS_RETURN_INVALID_PARAMETER); + RETURN_IF_NULL(name, GETDNS_RETURN_INVALID_PARAMETER); + response_status = validate_dname(name); + if (response_status != GETDNS_RETURN_GOOD) { + return response_status; + } response_status = validate_extensions(extensions); if (response_status == GETDNS_RETURN_GOOD) { response_status = getdns_general_ub(context->unbound_sync, diff --git a/src/util-internal.c b/src/util-internal.c index e71e559c..9769653e 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -11,7 +11,7 @@ /* * Copyright (c) 2013, Versign, Inc. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright @@ -374,7 +374,7 @@ add_only_addresses(struct getdns_list * addrs, ldns_rr_list * rr_list) int r = GETDNS_RETURN_GOOD; size_t i = 0; size_t item_idx = 0; - + r = getdns_list_get_length(addrs, &item_idx); for (i = 0; r == GETDNS_RETURN_GOOD && i < ldns_rr_list_rr_count(rr_list); ++i) { @@ -405,7 +405,7 @@ add_only_addresses(struct getdns_list * addrs, ldns_rr_list * rr_list) ? &IPv4_str_bindata : &IPv6_str_bindata)); r |= getdns_dict_set_bindata(this_address, GETDNS_STR_ADDRESS_DATA, &rbin); - r |= getdns_list_set_dict(addrs, item_idx++, + r |= getdns_list_set_dict(addrs, item_idx++, this_address); getdns_dict_destroy(this_address); } @@ -418,7 +418,7 @@ create_reply_dict(struct getdns_context *context, getdns_network_req * req, struct getdns_list * just_addrs) { /* turn a packet into this glorious structure - * + * * { # This is the first reply * "header": { "id": 23456, "qr": 1, "opcode": 0, ... }, * "question": { "qname": , "qtype": 1, "qclass": 1 }, @@ -454,7 +454,7 @@ create_reply_dict(struct getdns_context *context, getdns_network_req * req, * "canonical_name": , * "answer_type": GETDNS_NAMETYPE_DNS * } - * + * */ int r = 0; ldns_pkt *reply = req->result; @@ -677,4 +677,49 @@ validate_extensions(struct getdns_dict * extensions) return GETDNS_RETURN_GOOD; } /* validate_extensions */ +getdns_return_t +validate_dname(const char* dname) { + int len; + int label_len; + const char* s; + if (dname == NULL) { + return GETDNS_RETURN_INVALID_PARAMETER; + } + len = strlen(dname); + if (len >= GETDNS_MAX_DNAME_LEN || len == 0) { + return GETDNS_RETURN_BAD_DOMAIN_NAME; + } + if (len == 1 && dname[0] == '.') { + /* root is ok */ + return GETDNS_RETURN_GOOD; + } + label_len = 0; + for (s = dname; *s; ++s) { + switch (*s) { + case '.': + if (label_len > GETDNS_MAX_LABEL_LEN || + label_len == 0) { + return GETDNS_RETURN_BAD_DOMAIN_NAME; + } + label_len = 0; + break; + default: + if ((*s >= 'a' && *s <= 'z') || + (*s >= 'A' && *s <= 'Z') || + (*s >= '0' && *s <= '9')) { + label_len++; + } else if (*s == '-' && label_len != 0) { + label_len++; + } else { + return GETDNS_RETURN_BAD_DOMAIN_NAME; + } + break; + } + } + if (label_len > GETDNS_MAX_LABEL_LEN) { + return GETDNS_RETURN_BAD_DOMAIN_NAME; + } + return GETDNS_RETURN_GOOD; +} + /* util-internal.c */ diff --git a/src/util-internal.h b/src/util-internal.h index 04398957..d39b2c5d 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -10,7 +10,7 @@ /* * Copyright (c) 2013, Versign, Inc. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright @@ -41,6 +41,9 @@ #include #include "context.h" +#define GETDNS_MAX_DNAME_LEN 255 +#define GETDNS_MAX_LABEL_LEN 63 + /** * add an item to the tail of a list - note that this was not in the getdns API * description but the list_set functions seem to be designed to modify an existing @@ -96,6 +99,8 @@ getdns_return_t getdns_dict_util_get_string(struct getdns_dict * dict, char *nam char **result); char *reverse_address(struct getdns_bindata *address_data); +getdns_return_t validate_dname(const char* dname); + /** * detect unrecognized extension strings or invalid extension formats * TODO: this could be optimized by searching a sorted list