From: Wouter Wijngaards Date: Tue, 7 Dec 2010 12:49:17 +0000 (+0000) Subject: Fixes from Dan. X-Git-Tag: release-1.6.8rc1~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40ec90b85ec3575be26ddfba8eb5cd538d5c7170;p=thirdparty%2Fldns.git Fixes from Dan. --- diff --git a/Changelog b/Changelog index de827a16..290a45a6 100644 --- a/Changelog +++ b/Changelog @@ -1,5 +1,8 @@ 1.6.8 * Fix ldns zone, so that $TTL definition match RFC 2308. + * Fix lots of missing checks on allocation failures and parse of + NSEC with many types and max parse length in hosts_frm_fp routine + and off by one in read_anchor_file routine (thanks Dan Kaminsky). 1.6.7 2010-11-08 * EXPERIMENTAL ecdsa implementation, please do not enable on real diff --git a/dnssec.c b/dnssec.c index 5d394d1d..cdbc1906 100644 --- a/dnssec.c +++ b/dnssec.c @@ -679,6 +679,7 @@ ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], bm_len = i_type / 8 + 2; bitmap = LDNS_XMALLOC(uint8_t, bm_len); + if(!bitmap) return NULL; for (i = 0; i < bm_len; i++) { bitmap[i] = 0; } @@ -700,6 +701,10 @@ ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], data = LDNS_XREALLOC(data, uint8_t, cur_data_size + cur_window_max + 3); + if(!data) { + LDNS_FREE(bitmap); + return NULL; + } data[cur_data_size] = cur_window; data[cur_data_size + 1] = cur_window_max + 1; memcpy(data + cur_data_size + 2, @@ -721,6 +726,10 @@ ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], data = LDNS_XREALLOC(data, uint8_t, cur_data_size + cur_window_max + 3); + if(!data) { + LDNS_FREE(bitmap); + return NULL; + } data[cur_data_size] = cur_window; data[cur_data_size + 1] = cur_window_max + 1; memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1); @@ -964,6 +973,10 @@ ldns_nsec3_hash_name(ldns_rdf *name, hashed_owner_str_len = salt_length + ldns_rdf_size(cann); hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len); + if(!hashed_owner_str) { + ldns_rdf_deep_free(cann); + return NULL; + } memcpy(hashed_owner_str, ldns_rdf_data(cann), ldns_rdf_size(cann)); memcpy(hashed_owner_str + ldns_rdf_size(cann), salt, salt_length); ldns_rdf_deep_free(cann); @@ -976,7 +989,6 @@ ldns_nsec3_hash_name(ldns_rdf *name, hashed_owner_str_len = salt_length + LDNS_SHA1_DIGEST_LENGTH; hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len); if (!hashed_owner_str) { - fprintf(stderr, "Memory error\n"); return NULL; } memcpy(hashed_owner_str, hash, LDNS_SHA1_DIGEST_LENGTH); @@ -990,6 +1002,9 @@ ldns_nsec3_hash_name(ldns_rdf *name, hashed_owner_b32 = LDNS_XMALLOC(char, ldns_b32_ntop_calculate_size(hashed_owner_str_len) + 1); + if(!hashed_owner_b32) { + return NULL; + } hashed_owner_b32_len = (size_t) ldns_b32_ntop_extended_hex( (uint8_t *) hashed_owner_str, hashed_owner_str_len, @@ -1048,11 +1063,20 @@ ldns_nsec3_add_param_rdfs(ldns_rr *rr, if (old) ldns_rdf_deep_free(old); salt_data = LDNS_XMALLOC(uint8_t, salt_length + 1); + if(!salt_data) { + /* no way to return error */ + return; + } salt_data[0] = salt_length; memcpy(salt_data + 1, salt, salt_length); salt_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, salt_length + 1, salt_data); + if(!salt_rdf) { + LDNS_FREE(salt_data); + /* no way to return error */ + return; + } old = ldns_rr_set_rdf(rr, salt_rdf, 3); if (old) ldns_rdf_deep_free(old); @@ -1228,6 +1252,7 @@ ldns_nsec3_salt_data(const ldns_rr *nsec3_rr) if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { salt_length = ldns_rdf_data(salt_rdf)[0]; salt = LDNS_XMALLOC(uint8_t, salt_length); + if(!salt) return NULL; memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length); return salt; } @@ -1538,25 +1563,35 @@ ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig, (const unsigned char **)&dsasig_data, sig_len); if (!dsasig) { + DSA_SIG_free(dsasig); return NULL; } dsasig_data = LDNS_XMALLOC(unsigned char, 41); + if(!dsasig_data) { + DSA_SIG_free(dsasig); + return NULL; + } dsasig_data[0] = 0; byte_offset = (size_t) (20 - BN_num_bytes(dsasig->r)); if (byte_offset > 20) { + DSA_SIG_free(dsasig); return NULL; } memset(&dsasig_data[1], 0, byte_offset); BN_bn2bin(dsasig->r, &dsasig_data[1 + byte_offset]); byte_offset = (size_t) (20 - BN_num_bytes(dsasig->s)); if (byte_offset > 20) { + DSA_SIG_free(dsasig); return NULL; } memset(&dsasig_data[21], 0, byte_offset); BN_bn2bin(dsasig->s, &dsasig_data[21 + byte_offset]); sigdata_rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, 41, dsasig_data); + if(!sigdata_rdf) { + LDNS_FREE(dsasig_data); + } DSA_SIG_free(dsasig); return sigdata_rdf; diff --git a/dnssec_sign.c b/dnssec_sign.c index d571c93b..5d27761b 100644 --- a/dnssec_sign.c +++ b/dnssec_sign.c @@ -319,10 +319,18 @@ ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) return NULL; } - sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key); + if(!sig) { + ldns_buffer_free(b64sig); + return NULL; + } data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH); + if(!data) { + ldns_buffer_free(b64sig); + DSA_SIG_free(sig); + return NULL; + } data[0] = 1; pad = 20 - (size_t) BN_num_bytes(sig->r); @@ -343,6 +351,7 @@ ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) ldns_buffer_free(b64sig); LDNS_FREE(data); + DSA_SIG_free(sig); return sigdata_rdf; } diff --git a/dnssec_verify.c b/dnssec_verify.c index 11103dc2..775f7de0 100644 --- a/dnssec_verify.c +++ b/dnssec_verify.c @@ -19,6 +19,7 @@ ldns_dnssec_data_chain * ldns_dnssec_data_chain_new() { ldns_dnssec_data_chain *nc = LDNS_XMALLOC(ldns_dnssec_data_chain, 1); + if(!nc) return NULL; nc->rrset = NULL; nc->parent_type = 0; nc->parent = NULL; @@ -428,6 +429,7 @@ ldns_dnssec_trust_tree_new() { ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree, 1); + if(!new_tree) return NULL; new_tree->rr = NULL; new_tree->rrset = NULL; new_tree->parent_count = 0; @@ -494,6 +496,8 @@ ldns_dnssec_trust_tree_print_sm(FILE *out, if (!sibmap) { treedepth = ldns_dnssec_trust_tree_depth(tree); sibmap = malloc(treedepth); + if(!sibmap) + return; /* mem err */ memset(sibmap, 0, treedepth); mapset = true; } @@ -651,6 +655,8 @@ ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr) size_t i, j; ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new(); + if(!new_tree) + return NULL; if (data_chain && data_chain->rrset) { cur_rrset = data_chain->rrset; diff --git a/dnssec_zone.c b/dnssec_zone.c index 91e5651c..e258c433 100644 --- a/dnssec_zone.c +++ b/dnssec_zone.c @@ -11,6 +11,7 @@ ldns_dnssec_rrs_new() { ldns_dnssec_rrs *new_rrs; new_rrs = LDNS_MALLOC(ldns_dnssec_rrs); + if(!new_rrs) return NULL; new_rrs->rr = NULL; new_rrs->next = NULL; return new_rrs; @@ -96,6 +97,7 @@ ldns_dnssec_rrsets_new() { ldns_dnssec_rrsets *new_rrsets; new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets); + if(!new_rrsets) return NULL; new_rrsets->rrs = NULL; new_rrsets->type = 0; new_rrsets->signatures = NULL; @@ -555,6 +557,7 @@ ldns_dnssec_zone * ldns_dnssec_zone_new() { ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone); + if(!zone) return NULL; zone->soa = NULL; zone->names = NULL; @@ -653,6 +656,7 @@ ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) if (!zone->names) { zone->names = ldns_rbtree_create(ldns_dname_compare_v); + if(!zone->names) return LDNS_STATUS_MEM_ERR; } /* we need the original of the hashed name if this is @@ -675,6 +679,7 @@ ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) /* add */ cur_name = ldns_dnssec_name_new_frm_rr(rr); cur_node = LDNS_MALLOC(ldns_rbnode_t); + if(!cur_node) return LDNS_STATUS_MEM_ERR; cur_node->key = ldns_rr_owner(rr); cur_node->data = cur_name; ldns_rbtree_insert(zone->names, cur_node); diff --git a/higher.c b/higher.c index a4ab06f9..48e94def 100644 --- a/higher.c +++ b/higher.c @@ -173,8 +173,8 @@ ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr) return NULL; } - for(i = ldns_fget_token_l(fp, line, "\n", 0, line_nr); - i > 0; i = ldns_fget_token_l(fp, line, "\n", 0, line_nr)) { + for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr); + i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) { /* # is comment */ if (line[0] == '#') { continue; @@ -191,9 +191,9 @@ ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr) } ldns_buffer_new_frm_data(linebuf, line, (size_t) i); - for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, 0); + for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN); j > 0; - j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, 0), cnt++) { + j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) { if (cnt == 0) { /* the address */ if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, diff --git a/host2str.c b/host2str.c index 32ef8a5b..1031f211 100644 --- a/host2str.c +++ b/host2str.c @@ -761,6 +761,10 @@ ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf) uint8_t *data = ldns_rdf_data(rdf); + if(ldns_rdf_size(rdf) == 0) { + output->_status = LDNS_STATUS_ERR; + return ldns_buffer_status(output); + } salt_length = data[0]; /* from now there are variable length entries so remember pos */ if (salt_length == 0 || ((size_t)salt_length)+1 > ldns_rdf_size(rdf)) { @@ -887,6 +891,10 @@ ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf) /* Subtract the size (2) of the number that specifies the length */ size_t size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf) - 2); char *b64 = LDNS_XMALLOC(char, size); + if(!b64) { + output->_status = LDNS_STATUS_MEM_ERR; + return ldns_buffer_status(output); + } ldns_buffer_printf(output, "%u ", ldns_rdf_size(rdf) - 2); @@ -932,16 +940,28 @@ ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf) break; case 1: gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN); + if(!gateway_data) + return LDNS_STATUS_MEM_ERR; memcpy(gateway_data, &data[offset], LDNS_IP4ADDRLEN); gateway = ldns_rdf_new(LDNS_RDF_TYPE_A, LDNS_IP4ADDRLEN , gateway_data); offset += LDNS_IP4ADDRLEN; + if(!gateway) { + LDNS_FREE(gateway_data); + return LDNS_STATUS_MEM_ERR; + } break; case 2: gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN); + if(!gateway_data) + return LDNS_STATUS_MEM_ERR; memcpy(gateway_data, &data[offset], LDNS_IP6ADDRLEN); offset += LDNS_IP6ADDRLEN; gateway = ldns_rdf_new(LDNS_RDF_TYPE_AAAA, LDNS_IP6ADDRLEN, gateway_data); + if(!gateway) { + LDNS_FREE(gateway_data); + return LDNS_STATUS_MEM_ERR; + } break; case 3: status = ldns_wire2dname(&gateway, data, ldns_rdf_size(rdf), &offset); @@ -955,8 +975,17 @@ ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf) public_key_size = ldns_rdf_size(rdf) - offset; public_key_data = LDNS_XMALLOC(uint8_t, public_key_size); + if(!public_key_data) { + ldns_rdf_free(gateway); + return LDNS_STATUS_MEM_ERR; + } memcpy(public_key_data, &data[offset], public_key_size); public_key = ldns_rdf_new(LDNS_RDF_TYPE_B64, public_key_size, public_key_data); + if(!public_key) { + LDNS_FREE(public_key_data); + ldns_rdf_free(gateway); + return LDNS_STATUS_MEM_ERR; + } ldns_buffer_printf(output, "%u %u %u ", precedence, gateway_type, algorithm); if (gateway) @@ -1796,6 +1825,9 @@ ldns_buffer2str(ldns_buffer *buffer) tmp_str = ldns_buffer_export(buffer); str = LDNS_XMALLOC(char, strlen(tmp_str) + 1); + if(!str) { + return NULL; + } memcpy(str, tmp_str, strlen(tmp_str) + 1); return str; diff --git a/keys.c b/keys.c index e0fffc70..6bc71bb3 100644 --- a/keys.c +++ b/keys.c @@ -95,9 +95,15 @@ ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm ldns_key *k; k = ldns_key_new(); + if(!k) return LDNS_STATUS_MEM_ERR; k->_key.key = ENGINE_load_private_key(e, key_id, UI_OpenSSL(), NULL); + if(!k->_key.key) { + ldns_key_free(k); + return LDNS_STATUS_ERR; + } ldns_key_set_algorithm(k, (ldns_signing_algorithm) alg); if (!k->_key.key) { + ldns_key_free(k); return LDNS_STATUS_ENGINE_KEY_NOT_LOADED; } else { *key = k; @@ -295,6 +301,8 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); if (!k || !d) { + ldns_key_free(k); + LDNS_FREE(d); return LDNS_STATUS_MEM_ERR; } @@ -310,9 +318,13 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) if (ldns_fget_keyword_data_l(fp, "Private-key-format", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { /* no version information */ + ldns_key_free(k); + LDNS_FREE(d); return LDNS_STATUS_SYNTAX_ERR; } if (strncmp(d, "v1.2", strlen(d)) != 0) { + ldns_key_free(k); + LDNS_FREE(d); return LDNS_STATUS_SYNTAX_VERSION_ERR; } @@ -321,6 +333,8 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) if (ldns_fget_keyword_data_l(fp, "Algorithm", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { /* no alg information */ + ldns_key_free(k); + LDNS_FREE(d); return LDNS_STATUS_SYNTAX_ALG_ERR; } @@ -465,6 +479,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) #endif case 0: default: + ldns_key_free(k); return LDNS_STATUS_SYNTAX_ALG_ERR; } key_rr = ldns_key2rr(k); @@ -522,7 +537,7 @@ ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr) buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN); rsa = RSA_new(); if (!d || !rsa || !buf) { - return NULL; + goto error; } /* I could use functions again, but that seems an overkill, @@ -639,8 +654,8 @@ ldns_key_new_frm_fp_dsa_l(FILE *f, int *line_nr) d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN); dsa = DSA_new(); - if (!d || !dsa) { - return NULL; + if (!d || !dsa || !buf) { + goto error; } /* the line parser removes the () from the input... */ @@ -703,6 +718,7 @@ ldns_key_new_frm_fp_dsa_l(FILE *f, int *line_nr) error: LDNS_FREE(d); LDNS_FREE(buf); + DSA_free(dsa); return NULL; } @@ -723,6 +739,9 @@ ldns_key_new_frm_fp_hmac_l(FILE *f, int *line_nr, size_t *hmac_size) d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); buf = LDNS_XMALLOC(unsigned char, LDNS_MAX_LINELEN); + if(!d || !buf) { + goto error; + } if (ldns_fget_keyword_data_l(f, "Key", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; @@ -804,7 +823,12 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) case LDNS_SIGN_RSASHA512: #ifdef HAVE_SSL r = RSA_generate_key((int)size, RSA_F4, NULL, NULL); + if(!r) { + ldns_key_free(k); + return NULL; + } if (RSA_check_key(r) != 1) { + ldns_key_free(k); return NULL; } @@ -816,9 +840,11 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) #ifdef HAVE_SSL d = DSA_generate_parameters((int)size, NULL, 0, NULL, NULL, NULL, NULL); if (!d) { + ldns_key_free(k); return NULL; } if (DSA_generate_key(d) != 1) { + ldns_key_free(k); return NULL; } ldns_key_set_dsa_key(k, d); @@ -834,6 +860,10 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) ldns_key_set_hmac_size(k, size); hmac = LDNS_XMALLOC(unsigned char, size); + if(!hmac) { + ldns_key_free(k); + return NULL; + } #ifdef HAVE_SSL if (RAND_bytes(hmac, (int) size) != 1) { LDNS_FREE(hmac); @@ -858,6 +888,10 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) case LDNS_SIGN_ECC_GOST: #if defined(HAVE_SSL) && defined(USE_GOST) ldns_key_set_evp_key(k, ldns_gen_gost_key()); + if(!k->_key.key) { + ldns_key_free(k); + return NULL; + } #endif /* HAVE_SSL and USE_GOST */ break; #ifdef USE_ECDSA @@ -867,13 +901,18 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); else if(alg == LDNS_ECDSAP384SHA384) ec = EC_KEY_new_by_curve_name(NID_secp384r1); - if(!ec) return NULL; + if(!ec) { + ldns_key_free(k); + return NULL; + } if(!EC_KEY_generate_key(ec)) { + ldns_key_free(k); EC_KEY_free(ec); return NULL; } k->_key.key = EVP_PKEY_new(); if(!k->_key.key) { + ldns_key_free(k); EC_KEY_free(ec); return NULL; } @@ -1156,6 +1195,7 @@ ldns_key * ldns_key_list_pop_key(ldns_key_list *key_list) { size_t key_count; + ldns_key** a; ldns_key *pop; if (!key_list) { @@ -1170,8 +1210,11 @@ ldns_key_list_pop_key(ldns_key_list *key_list) pop = ldns_key_list_key(key_list, key_count); /* shrink the array */ - key_list->_keys = LDNS_XREALLOC( - key_list->_keys, ldns_key *, key_count - 1); + a = LDNS_XREALLOC(key_list->_keys, ldns_key *, key_count - 1); + if(!a) { + return NULL; + } + key_list->_keys = a; ldns_key_list_set_key_count(key_list, key_count - 1); @@ -1179,6 +1222,7 @@ ldns_key_list_pop_key(ldns_key_list *key_list) } #ifdef HAVE_SSL +/* data pointer must be large enough (LDNS_MAX_KEYLEN) */ static bool ldns_key_rsa2bin(unsigned char *data, RSA *k, uint16_t *size) { @@ -1210,6 +1254,7 @@ ldns_key_rsa2bin(unsigned char *data, RSA *k, uint16_t *size) return true; } +/* data pointer must be large enough (LDNS_MAX_KEYLEN) */ static bool ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size) { @@ -1323,9 +1368,12 @@ ldns_key2rr(const ldns_key *k) if (rsa) { bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); if (!bin) { + ldns_rr_free(pubkey); return NULL; } if (!ldns_key_rsa2bin(bin, rsa, &size)) { + LDNS_FREE(bin); + ldns_rr_free(pubkey); return NULL; } RSA_free(rsa); @@ -1342,9 +1390,12 @@ ldns_key2rr(const ldns_key *k) if (dsa) { bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); if (!bin) { + ldns_rr_free(pubkey); return NULL; } if (!ldns_key_dsa2bin(bin, dsa, &size)) { + LDNS_FREE(bin); + ldns_rr_free(pubkey); return NULL; } DSA_free(dsa); @@ -1360,9 +1411,12 @@ ldns_key2rr(const ldns_key *k) if (dsa) { bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); if (!bin) { + ldns_rr_free(pubkey); return NULL; } if (!ldns_key_dsa2bin(bin, dsa, &size)) { + LDNS_FREE(bin); + ldns_rr_free(pubkey); return NULL; } DSA_free(dsa); @@ -1375,9 +1429,13 @@ ldns_key2rr(const ldns_key *k) LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); #if defined(HAVE_SSL) && defined(USE_GOST) bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); - if (!bin) + if (!bin) { + ldns_rr_free(pubkey); return NULL; + } if (!ldns_key_gost2bin(bin, k->_key.key, &size)) { + LDNS_FREE(bin); + ldns_rr_free(pubkey); return NULL; } internal_data = 1; @@ -1392,8 +1450,11 @@ ldns_key2rr(const ldns_key *k) ec = EVP_PKEY_get1_EC_KEY(k->_key.key); EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); size = i2o_ECPublicKey(ec, NULL); - if(!i2o_ECPublicKey(ec, &bin)) + if(!i2o_ECPublicKey(ec, &bin)) { + EC_KEY_free(ec); + ldns_rr_free(pubkey); return NULL; + } if(size > 1) { /* move back one byte to shave off the 0x02 * 'uncompressed' indicator that openssl made @@ -1414,6 +1475,7 @@ ldns_key2rr(const ldns_key *k) case LDNS_SIGN_HMACSHA256: bin = LDNS_XMALLOC(unsigned char, ldns_key_hmac_size(k)); if (!bin) { + ldns_rr_free(pubkey); return NULL; } ldns_rr_push_rdf(pubkey, @@ -1477,6 +1539,9 @@ ldns_read_anchor_file(const char *filename) size_t i = 0; ldns_rr *r; ldns_status status; + if(!line) { + return NULL; + } fp = fopen(filename, "r"); if (!fp) { @@ -1485,7 +1550,7 @@ ldns_read_anchor_file(const char *filename) return NULL; } - while ((c = fgetc(fp)) && i < LDNS_MAX_PACKETLEN && c != EOF) { + while ((c = fgetc(fp)) && i+1 < LDNS_MAX_PACKETLEN && c != EOF) { line[i] = c; i++; } diff --git a/net.c b/net.c index 1b067545..58aa67f1 100644 --- a/net.c +++ b/net.c @@ -546,6 +546,10 @@ ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout) LDNS_FREE(wire); wire = LDNS_XMALLOC(uint8_t, wire_size); + if (!wire) { + *size = 0; + return NULL; + } bytes = 0; while (bytes < (ssize_t) wire_size) { @@ -596,6 +600,10 @@ ldns_tcp_read_wire(int sockfd, size_t *size) LDNS_FREE(wire); wire = LDNS_XMALLOC(uint8_t, wire_size); + if (!wire) { + *size = 0; + return NULL; + } bytes = 0; while (bytes < (ssize_t) wire_size) { @@ -644,6 +652,8 @@ ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storag /* resize accordingly */ answer = (uint8_t*)LDNS_XREALLOC(answer, uint8_t *, (size_t)*answer_size); *result = answer; + if(!answer) + return LDNS_STATUS_MEM_ERR; return LDNS_STATUS_OK; } @@ -805,6 +815,18 @@ ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) * Is this necessary? */ query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if(!query_wire) { + ldns_pkt_free(query); + LDNS_FREE(ns); +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + + return LDNS_STATUS_MEM_ERR; + } status = ldns_pkt2buffer_wire(query_wire, query); if (status != LDNS_STATUS_OK) { ldns_pkt_free(query); diff --git a/parse.c b/parse.c index 9e119751..04878735 100644 --- a/parse.c +++ b/parse.c @@ -183,6 +183,8 @@ ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char * char *fkeyword; ssize_t i; + if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN) + return -1; fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN); if(!fkeyword) return -1; @@ -416,6 +418,8 @@ ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, c char *fkeyword; ssize_t i; + if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN) + return -1; fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN); if(!fkeyword) return -1; /* out of memory */ diff --git a/resolver.c b/resolver.c index db238c37..e49ab86f 100644 --- a/resolver.c +++ b/resolver.c @@ -254,7 +254,9 @@ ldns_resolver_pop_nameserver(ldns_resolver *r) pop = nameservers[ns_count - 1]; nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count - 1)); + if(!nameservers) return NULL; rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1)); + if(!rtt) return NULL; ldns_resolver_set_nameservers(r, nameservers); ldns_resolver_set_rtt(r, rtt); @@ -281,8 +283,12 @@ ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n) /* make room for the next one */ nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1)); + if(!nameservers) + return LDNS_STATUS_MEM_ERR; /* don't forget the rtt */ rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1)); + if(!rtt) + return LDNS_STATUS_MEM_ERR; /* set the new value in the resolver */ ldns_resolver_set_nameservers(r, nameservers); diff --git a/rr.c b/rr.c index 60ce4985..8e84fd61 100644 --- a/rr.c +++ b/rr.c @@ -53,6 +53,10 @@ ldns_rr_new_frm_type(ldns_rr_type t) desc = ldns_rr_descript(t); rr->_rdata_fields = LDNS_XMALLOC(ldns_rdf *, ldns_rr_descriptor_minimum(desc)); + if(!rr->_rdata_fields) { + LDNS_FREE(rr); + return NULL; + } for (i = 0; i < ldns_rr_descriptor_minimum(desc); i++) { rr->_rdata_fields[i] = NULL; } @@ -144,6 +148,15 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, rd = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); b64 = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); if (!new || !owner || !ttl || !clas || !rdata || !rr_buf || !rd_buf || !rd || !b64 ) { + ldns_rr_free(new); + LDNS_FREE(owner); + LDNS_FREE(ttl); + LDNS_FREE(clas); + LDNS_FREE(rdata); + LDNS_FREE(rr_buf); + LDNS_FREE(rd_buf); + LDNS_FREE(rd); + LDNS_FREE(b64); return LDNS_STATUS_MEM_ERR; } @@ -196,6 +209,18 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, if (clas_val == 0) { clas_val = LDNS_RR_CLASS_IN; type = LDNS_XMALLOC(char, strlen(ttl) + 1); + if(!type) { + ldns_rr_free(new); + LDNS_FREE(owner); + LDNS_FREE(ttl); + LDNS_FREE(clas); + LDNS_FREE(rdata); + ldns_buffer_free(rr_buf); + LDNS_FREE(rd_buf); + LDNS_FREE(rd); + LDNS_FREE(b64); + return LDNS_STATUS_MEM_ERR; + } strncpy(type, ttl, strlen(ttl) + 1); } } else { @@ -218,6 +243,18 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, if (clas_val == 0) { clas_val = LDNS_RR_CLASS_IN; type = LDNS_XMALLOC(char, strlen(clas) + 1); + if(!type) { + ldns_rr_free(new); + LDNS_FREE(owner); + LDNS_FREE(ttl); + LDNS_FREE(clas); + LDNS_FREE(rdata); + ldns_buffer_free(rr_buf); + LDNS_FREE(rd_buf); + LDNS_FREE(rd); + LDNS_FREE(b64); + return LDNS_STATUS_MEM_ERR; + } strncpy(type, clas, strlen(clas) + 1); } } @@ -271,6 +308,19 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, if (prev) { ldns_rdf_deep_free(*prev); *prev = ldns_rdf_clone(ldns_rr_owner(new)); + if(!*prev) { + LDNS_FREE(owner); + LDNS_FREE(ttl); + LDNS_FREE(clas); + LDNS_FREE(type); + LDNS_FREE(rdata); + LDNS_FREE(rd); + LDNS_FREE(rd_buf); + LDNS_FREE(b64); + ldns_buffer_free(rr_buf); + ldns_rr_free(new); + return LDNS_STATUS_MEM_ERR; + } } } else { if (strlen(owner) == 0) { @@ -283,6 +333,19 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, } else { ldns_rr_set_owner(new, ldns_dname_new_frm_str(".")); } + if(!ldns_rr_owner(new)) { + LDNS_FREE(owner); + LDNS_FREE(ttl); + LDNS_FREE(clas); + LDNS_FREE(type); + LDNS_FREE(rdata); + LDNS_FREE(rd); + LDNS_FREE(rd_buf); + LDNS_FREE(b64); + ldns_buffer_free(rr_buf); + ldns_rr_free(new); + return LDNS_STATUS_MEM_ERR; + } } else { owner_dname = ldns_dname_new_frm_str(owner); if (!owner_dname) { @@ -319,6 +382,19 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, if (prev) { ldns_rdf_deep_free(*prev); *prev = ldns_rdf_clone(ldns_rr_owner(new)); + if(!*prev) { + LDNS_FREE(owner); + LDNS_FREE(ttl); + LDNS_FREE(clas); + LDNS_FREE(type); + LDNS_FREE(rdata); + LDNS_FREE(rd); + LDNS_FREE(rd_buf); + LDNS_FREE(b64); + ldns_buffer_free(rr_buf); + ldns_rr_free(new); + return LDNS_STATUS_MEM_ERR; + } } } } @@ -420,8 +496,12 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, c = ldns_bget_token(rd_buf, rd, delimiters, LDNS_MAX_RDFLEN); if (c == -1) { /* something goes very wrong here */ - ldns_buffer_free(rd_buf); - LDNS_FREE(rd); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); return LDNS_STATUS_SYNTAX_RDATA_ERR; } hex_data_size = (uint16_t) atoi(rd); @@ -429,8 +509,12 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, hex_data_str = LDNS_XMALLOC(char, 2 * hex_data_size + 1); if (!hex_data_str) { /* malloc error */ - ldns_buffer_free(rd_buf); - LDNS_FREE(rd); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); return LDNS_STATUS_SYNTAX_RDATA_ERR; } cur_hex_data_size = 0; @@ -447,15 +531,55 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, if (desc) { size_t hex_pos = 0; uint8_t *hex_data = LDNS_XMALLOC(uint8_t, hex_data_size + 2); + ldns_status s; + if(!hex_data) { + LDNS_FREE(hex_data_str); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_MEM_ERR; + } ldns_write_uint16(hex_data, hex_data_size); ldns_hexstring_to_data(hex_data + 2, hex_data_str); - (void) ldns_wire2rdf(new, hex_data, + s = ldns_wire2rdf(new, hex_data, hex_data_size+2, &hex_pos); + if(s != LDNS_STATUS_OK) { + LDNS_FREE(hex_data_str); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return s; + } LDNS_FREE(hex_data); } else { r = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_HEX, hex_data_str); + if(!r) { + LDNS_FREE(hex_data_str); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_MEM_ERR; + } ldns_rdf_set_type(r, LDNS_RDF_TYPE_UNKNOWN); - ldns_rr_push_rdf(new, r); + if(!ldns_rr_push_rdf(new, r)) { + LDNS_FREE(hex_data_str); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_MEM_ERR; + } } LDNS_FREE(hex_data_str); } else { @@ -500,6 +624,12 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, } } else if (r && rd_strlen >= 1 && !ldns_dname_str_absolute(rd) && origin) { if (ldns_dname_cat(r, origin) != LDNS_STATUS_OK) { + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); return LDNS_STATUS_ERR; } } @@ -865,6 +995,7 @@ ldns_rr_list * ldns_rr_list_new() { ldns_rr_list *rr_list = LDNS_MALLOC(ldns_rr_list); + if(!rr_list) return NULL; rr_list->_rr_count = 0; rr_list->_rr_capacity = 0; rr_list->_rrs = NULL; @@ -1055,8 +1186,11 @@ ldns_rr_list_pop_rr(ldns_rr_list *rr_list) /* shrink the array */ if(cap > LDNS_RRLIST_INIT && rr_count-1 <= cap/2) { + ldns_rr** a; cap /= 2; - rr_list->_rrs = LDNS_XREALLOC(rr_list->_rrs, ldns_rr *, cap); + a = LDNS_XREALLOC(rr_list->_rrs, ldns_rr *, cap); + if(!a) return NULL; + rr_list->_rrs = a; rr_list->_rr_capacity = cap; } @@ -1358,6 +1492,8 @@ qsort_schwartz_rr_compare(const void *a, const void *b) ldns_rr2canonical(canonical_a); sa->transformed_object = ldns_buffer_new(ldns_rr_uncompressed_size(canonical_a)); if (ldns_rr2buffer_wire(sa->transformed_object, canonical_a, LDNS_SECTION_ANY) != LDNS_STATUS_OK) { + ldns_buffer_free((ldns_buffer *)sa->transformed_object); + sa->transformed_object = NULL; ldns_rr_free(canonical_a); return 0; } @@ -1368,6 +1504,10 @@ qsort_schwartz_rr_compare(const void *a, const void *b) ldns_rr2canonical(canonical_b); sb->transformed_object = ldns_buffer_new(ldns_rr_uncompressed_size(canonical_b)); if (ldns_rr2buffer_wire(sb->transformed_object, canonical_b, LDNS_SECTION_ANY) != LDNS_STATUS_OK) { + ldns_buffer_free((ldns_buffer *)sa->transformed_object); + ldns_buffer_free((ldns_buffer *)sb->transformed_object); + sa->transformed_object = NULL; + sb->transformed_object = NULL; ldns_rr_free(canonical_b); return 0; } @@ -1394,8 +1534,18 @@ ldns_rr_list_sort(ldns_rr_list *unsorted) sortables = LDNS_XMALLOC(struct ldns_schwartzian_compare_struct *, item_count); + if(!sortables) return; /* no way to return error */ for (i = 0; i < item_count; i++) { sortables[i] = LDNS_XMALLOC(struct ldns_schwartzian_compare_struct, 1); + if(!sortables[i]) { + /* free the allocated parts */ + while(i>0) { + i--; + LDNS_FREE(sortables[i]); + } + /* no way to return error */ + return; + } sortables[i]->original_object = ldns_rr_list_rr(unsorted, i); sortables[i]->transformed_object = NULL; } diff --git a/str2host.c b/str2host.c index f73b23d2..c4034537 100644 --- a/str2host.c +++ b/str2host.c @@ -38,6 +38,7 @@ ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr) char *end = NULL; uint16_t *r; r = LDNS_MALLOC(uint16_t); + if(!r) return LDNS_STATUS_MEM_ERR; *r = htons((uint16_t)strtol((char *)shortstr, &end, 10)); @@ -48,7 +49,7 @@ ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr) *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r); LDNS_FREE(r); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } } @@ -63,6 +64,7 @@ ldns_str2rdf_time(ldns_rdf **rd, const char *time) /* Try to scan the time... */ r = (uint16_t*)LDNS_MALLOC(uint32_t); + if(!r) return LDNS_STATUS_MEM_ERR; memset(&tm, 0, sizeof(tm)); @@ -99,7 +101,7 @@ ldns_str2rdf_time(ldns_rdf **rd, const char *time) *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r); LDNS_FREE(r); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } else { /* handle it as 32 bits timestamp */ l = htonl((uint32_t)strtol((char*)time, &end, 10)); @@ -111,7 +113,7 @@ ldns_str2rdf_time(ldns_rdf **rd, const char *time) *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); LDNS_FREE(r); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } } @@ -129,6 +131,9 @@ ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str) uint8_t *salt; uint8_t *data; + if(rd == NULL) { + return LDNS_STATUS_NULL; + } salt_length_str = strlen(salt_str); if (salt_length_str == 1 && salt_str[0] == '-') { @@ -141,6 +146,9 @@ ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str) } salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2); + if(!salt) { + return LDNS_STATUS_MEM_ERR; + } for (c = 0; c < salt_length_str; c += 2) { if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) { salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 + @@ -153,13 +161,17 @@ ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str) salt_length = (uint8_t) (salt_length_str / 2); data = LDNS_XMALLOC(uint8_t, 1 + salt_length); + if(!data) { + LDNS_FREE(salt); + return LDNS_STATUS_MEM_ERR; + } data[0] = salt_length; memcpy(&data[1], salt, salt_length); *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data); LDNS_FREE(data); LDNS_FREE(salt); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -178,7 +190,7 @@ ldns_str2rdf_period(ldns_rdf **rd,const char *period) *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p); } - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -189,6 +201,7 @@ ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr) uint32_t l; r = (uint16_t*)LDNS_MALLOC(uint32_t); + if(!r) return LDNS_STATUS_MEM_ERR; errno = 0; /* must set to zero before call, note race condition on errno */ if(*longstr == '-') @@ -207,7 +220,7 @@ ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr) *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); LDNS_FREE(r); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } } @@ -218,6 +231,7 @@ ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr) uint8_t *r = NULL; r = LDNS_MALLOC(uint8_t); + if(!r) return LDNS_STATUS_MEM_ERR; *r = (uint8_t)strtol((char*)bytestr, &end, 10); @@ -228,7 +242,7 @@ ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr) *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r); LDNS_FREE(r); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } } @@ -375,7 +389,7 @@ ldns_str2rdf_a(ldns_rdf **rd, const char *str) *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A, sizeof(address), &address); } - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -389,7 +403,7 @@ ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str) *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address); } - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -403,6 +417,7 @@ ldns_str2rdf_str(ldns_rdf **rd, const char *str) } data = LDNS_XMALLOC(uint8_t, strlen(str) + 1); + if(!data) return LDNS_STATUS_MEM_ERR; i = 1; for (str_i = 0; str_i < strlen(str); str_i++) { if (str[str_i] == '\\') { @@ -421,7 +436,7 @@ ldns_str2rdf_str(ldns_rdf **rd, const char *str) data[0] = i - 1; *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_STR, i, data); LDNS_FREE(data); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -461,13 +476,20 @@ ldns_str2rdf_apl(ldns_rdf **rd, const char *str) /* need ip addr and only ip addr for inet_pton */ ip_str_len = (size_t) (strchr(my_str, '/') - my_str); my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1); + if(!my_ip_str) return LDNS_STATUS_MEM_ERR; strncpy(my_ip_str, my_str, ip_str_len + 1); my_ip_str[ip_str_len] = '\0'; if (family == 1) { /* ipv4 */ afdpart = LDNS_XMALLOC(uint8_t, 4); + if(!afdpart) { + LDNS_FREE(my_ip_str); + return LDNS_STATUS_MEM_ERR; + } if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) { + LDNS_FREE(my_ip_str); + LDNS_FREE(afdpart); return LDNS_STATUS_INVALID_STR; } for (i = 0; i < 4; i++) { @@ -478,7 +500,13 @@ ldns_str2rdf_apl(ldns_rdf **rd, const char *str) } else if (family == 2) { /* ipv6 */ afdpart = LDNS_XMALLOC(uint8_t, 16); + if(!afdpart) { + LDNS_FREE(my_ip_str); + return LDNS_STATUS_MEM_ERR; + } if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) { + LDNS_FREE(my_ip_str); + LDNS_FREE(afdpart); return LDNS_STATUS_INVALID_STR; } for (i = 0; i < 16; i++) { @@ -496,6 +524,10 @@ ldns_str2rdf_apl(ldns_rdf **rd, const char *str) prefix = (uint8_t) atoi(my_str); data = LDNS_XMALLOC(uint8_t, 4 + afdlength); + if(!data) { + LDNS_FREE(my_ip_str); + return LDNS_STATUS_INVALID_STR; + } ldns_write_uint16(data, family); data[2] = prefix; data[3] = afdlength; @@ -511,7 +543,7 @@ ldns_str2rdf_apl(ldns_rdf **rd, const char *str) LDNS_FREE(data); LDNS_FREE(my_ip_str); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -521,6 +553,9 @@ ldns_str2rdf_b64(ldns_rdf **rd, const char *str) int16_t i; buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str))); + if(!buffer) { + return LDNS_STATUS_MEM_ERR; + } i = (uint16_t)ldns_b64_pton((const char*)str, buffer, ldns_b64_ntop_calculate_size(strlen(str))); @@ -533,7 +568,7 @@ ldns_str2rdf_b64(ldns_rdf **rd, const char *str) } LDNS_FREE(buffer); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -544,11 +579,15 @@ ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str) /* first byte contains length of actual b32 data */ uint8_t len = ldns_b32_pton_calculate_size(strlen(str)); buffer = LDNS_XMALLOC(uint8_t, len + 1); + if(!buffer) { + return LDNS_STATUS_MEM_ERR; + } buffer[0] = len; i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1, ldns_b32_ntop_calculate_size(strlen(str))); if (i < 0) { + LDNS_FREE(buffer); return LDNS_STATUS_INVALID_B32_EXT; } else { *rd = ldns_rdf_new_frm_data( @@ -556,7 +595,7 @@ ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str) } LDNS_FREE(buffer); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -572,6 +611,9 @@ ldns_str2rdf_hex(ldns_rdf **rd, const char *str) return LDNS_STATUS_LABEL_OVERFLOW; } else { t = LDNS_XMALLOC(uint8_t, (len / 2) + 1); + if(!t) { + return LDNS_STATUS_MEM_ERR; + } t_orig = t; /* Now process octet by octet... */ while (*str) { @@ -585,6 +627,7 @@ ldns_str2rdf_hex(ldns_rdf **rd, const char *str) if (isxdigit((int) *str)) { *t += ldns_hexdigit_to_int(*str) * i; } else { + LDNS_FREE(t_orig); return LDNS_STATUS_ERR; } ++str; @@ -598,7 +641,7 @@ ldns_str2rdf_hex(ldns_rdf **rd, const char *str) t_orig); LDNS_FREE(t_orig); } - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -610,7 +653,7 @@ ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) ssize_t c; uint16_t cur_type; size_t type_count = 0; - ldns_rr_type type_list[1024]; + ldns_rr_type type_list[65536]; if(!token) return LDNS_STATUS_MEM_ERR; if(rd == NULL) { LDNS_FREE(token); @@ -630,6 +673,11 @@ ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) } while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) { + if(type_count >= sizeof(type_list)) { + LDNS_FREE(str_buf); + LDNS_FREE(token); + return LDNS_STATUS_ERR; + } cur_type = ldns_get_rr_type_by_name(token); type_list[type_count] = cur_type; type_count++; @@ -641,7 +689,7 @@ ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) LDNS_FREE(token); ldns_buffer_free(str_buf); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -652,7 +700,7 @@ ldns_str2rdf_type(ldns_rdf **rd, const char *str) /* ldns_rr_type is a 16 bit value */ *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status @@ -663,7 +711,7 @@ ldns_str2rdf_class(ldns_rdf **rd, const char *str) /* class is 16 bit */ *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } /* An certificate alg field can either be specified as a 8 bits number @@ -942,6 +990,9 @@ east: } data = LDNS_XMALLOC(uint8_t, 16); + if(!data) { + return LDNS_STATUS_MEM_ERR; + } data[0] = 0; data[1] = 0; data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); @@ -955,7 +1006,7 @@ east: LDNS_RDF_TYPE_LOC, 16, data); LDNS_FREE(data); - return LDNS_STATUS_OK; + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status diff --git a/tsig.c b/tsig.c index 40839609..b2882f1e 100644 --- a/tsig.c +++ b/tsig.c @@ -66,6 +66,9 @@ ldns_tsig_prepare_pkt_wire(uint8_t *wire, size_t wire_len, size_t *result_len) ldns_status status; + if(wire_len < LDNS_HEADER_SIZE) { + return LDNS_STATUS_WIRE_INCOMPLETE_HEADER; + } /* fake parse the wire */ qd_count = LDNS_QDCOUNT(wire); an_count = LDNS_ANCOUNT(wire); @@ -115,6 +118,9 @@ ldns_tsig_prepare_pkt_wire(uint8_t *wire, size_t wire_len, size_t *result_len) *result_len = pos; wire2 = LDNS_XMALLOC(uint8_t, *result_len); + if(!wire2) { + return NULL; + } memcpy(wire2, wire, *result_len); ldns_write_uint16(wire2 + LDNS_ARCOUNT_OFF, ar_count); @@ -330,7 +336,6 @@ ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const ch #endif /* HAVE_SSL */ #ifdef HAVE_SSL -/* TODO: memory :p */ ldns_status ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac) @@ -361,11 +366,19 @@ ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_dat ldns_rdf *time_signed_rdf = NULL; algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name); + if(!key_name_rdf || !algorithm_rdf) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } /* eww don't have create tsigtime rdf yet :( */ /* bleh :p */ if (gettimeofday(&tv_time_signed, NULL) == 0) { time_signed = LDNS_XMALLOC(uint8_t, 6); + if(!time_signed) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } ldns_write_uint64_as_uint48(time_signed, (uint64_t)tv_time_signed.tv_sec); } else { @@ -374,6 +387,11 @@ ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_dat } time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed); + if(!time_signed_rdf) { + LDNS_FREE(time_signed); + status = LDNS_STATUS_MEM_ERR; + goto clean; + } fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge); @@ -383,6 +401,11 @@ ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_dat other_data_rdf = ldns_native2rdf_int16_data(0, NULL); + if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } + if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) { status = LDNS_STATUS_ERR; goto clean; @@ -400,6 +423,10 @@ ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_dat /* Create the TSIG RR */ tsig_rr = ldns_rr_new(); + if(!tsig_rr) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } ldns_rr_set_owner(tsig_rr, key_name_rdf); ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY); ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG); @@ -418,6 +445,7 @@ ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_dat return status; clean: + LDNS_FREE(pkt_wire); ldns_rdf_free(key_name_rdf); ldns_rdf_free(algorithm_rdf); ldns_rdf_free(time_signed_rdf); diff --git a/util.c b/util.c index 3b446ba7..5870bb6e 100644 --- a/util.c +++ b/util.c @@ -270,6 +270,9 @@ ldns_init_random(FILE *fd, unsigned int size) } seed = LDNS_XMALLOC(uint8_t, size); + if(!seed) { + return 1; + } if (!fd) { if ((rand_f = fopen("/dev/urandom", "r")) == NULL) {