1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /* $Id: nsec3_50.c,v 1.12 2020/02/26 18:49:02 florian Exp $ */ 18 19 /* 20 * Copyright (C) 2004 Nominet, Ltd. 21 * 22 * Permission to use, copy, modify, and distribute this software for any 23 * purpose with or without fee is hereby granted, provided that the above 24 * copyright notice and this permission notice appear in all copies. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH 27 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 28 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 29 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 30 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 31 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 32 * PERFORMANCE OF THIS SOFTWARE. 33 */ 34 35 /* RFC 5155 */ 36 37 #ifndef RDATA_GENERIC_NSEC3_50_C 38 #define RDATA_GENERIC_NSEC3_50_C 39 40 #include <isc/base32.h> 41 42 static inline isc_result_t 43 totext_nsec3(ARGS_TOTEXT) { 44 isc_region_t sr; 45 unsigned int i, j; 46 unsigned char hash; 47 unsigned char flags; 48 char buf[sizeof("TYPE65535")]; 49 uint32_t iterations; 50 51 REQUIRE(rdata->type == dns_rdatatype_nsec3); 52 REQUIRE(rdata->length != 0); 53 54 dns_rdata_toregion(rdata, &sr); 55 56 /* Hash */ 57 hash = uint8_fromregion(&sr); 58 isc_region_consume(&sr, 1); 59 snprintf(buf, sizeof(buf), "%u ", hash); 60 RETERR(isc_str_tobuffer(buf, target)); 61 62 /* Flags */ 63 flags = uint8_fromregion(&sr); 64 isc_region_consume(&sr, 1); 65 snprintf(buf, sizeof(buf), "%u ", flags); 66 RETERR(isc_str_tobuffer(buf, target)); 67 68 /* Iterations */ 69 iterations = uint16_fromregion(&sr); 70 isc_region_consume(&sr, 2); 71 snprintf(buf, sizeof(buf), "%u ", iterations); 72 RETERR(isc_str_tobuffer(buf, target)); 73 74 /* Salt */ 75 j = uint8_fromregion(&sr); 76 isc_region_consume(&sr, 1); 77 INSIST(j <= sr.length); 78 79 if (j != 0) { 80 i = sr.length; 81 sr.length = j; 82 RETERR(isc_hex_totext(&sr, 1, "", target)); 83 sr.length = i - j; 84 } else 85 RETERR(isc_str_tobuffer("-", target)); 86 87 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 88 RETERR(isc_str_tobuffer(" (", target)); 89 RETERR(isc_str_tobuffer(tctx->linebreak, target)); 90 91 /* Next hash */ 92 j = uint8_fromregion(&sr); 93 isc_region_consume(&sr, 1); 94 INSIST(j <= sr.length); 95 96 i = sr.length; 97 sr.length = j; 98 RETERR(isc_base32hexnp_totext(&sr, 1, "", target)); 99 sr.length = i - j; 100 101 /* 102 * Don't leave a trailing space when there's no typemap present. 103 */ 104 if (((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0) && (sr.length > 0)) { 105 RETERR(isc_str_tobuffer(" ", target)); 106 } 107 RETERR(typemap_totext(&sr, tctx, target)); 108 109 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 110 RETERR(isc_str_tobuffer(" )", target)); 111 112 return (ISC_R_SUCCESS); 113 } 114 115 static inline isc_result_t 116 fromwire_nsec3(ARGS_FROMWIRE) { 117 isc_region_t sr, rr; 118 unsigned int saltlen, hashlen; 119 120 REQUIRE(type == dns_rdatatype_nsec3); 121 122 UNUSED(type); 123 UNUSED(rdclass); 124 UNUSED(options); 125 UNUSED(dctx); 126 127 isc_buffer_activeregion(source, &sr); 128 rr = sr; 129 130 /* hash(1), flags(1), iteration(2), saltlen(1) */ 131 if (sr.length < 5U) 132 return (DNS_R_FORMERR); 133 saltlen = sr.base[4]; 134 isc_region_consume(&sr, 5); 135 136 if (sr.length < saltlen) 137 return (DNS_R_FORMERR); 138 isc_region_consume(&sr, saltlen); 139 140 if (sr.length < 1U) 141 return (DNS_R_FORMERR); 142 hashlen = sr.base[0]; 143 isc_region_consume(&sr, 1); 144 145 if (sr.length < hashlen) 146 return (DNS_R_FORMERR); 147 isc_region_consume(&sr, hashlen); 148 149 RETERR(typemap_test(&sr, ISC_TRUE)); 150 151 RETERR(isc_mem_tobuffer(target, rr.base, rr.length)); 152 isc_buffer_forward(source, rr.length); 153 return (ISC_R_SUCCESS); 154 } 155 156 static inline isc_result_t 157 towire_nsec3(ARGS_TOWIRE) { 158 isc_region_t sr; 159 160 REQUIRE(rdata->type == dns_rdatatype_nsec3); 161 REQUIRE(rdata->length != 0); 162 163 UNUSED(cctx); 164 165 dns_rdata_toregion(rdata, &sr); 166 return (isc_mem_tobuffer(target, sr.base, sr.length)); 167 } 168 169 #define NSEC3_MAX_HASH_LENGTH 155 170 static inline isc_boolean_t 171 checkowner_nsec3(ARGS_CHECKOWNER) { 172 unsigned char owner[NSEC3_MAX_HASH_LENGTH]; 173 isc_buffer_t buffer; 174 dns_label_t label; 175 176 REQUIRE(type == dns_rdatatype_nsec3); 177 178 UNUSED(type); 179 UNUSED(rdclass); 180 UNUSED(wildcard); 181 182 /* 183 * First label is a base32hex string without padding. 184 */ 185 dns_name_getlabel(name, 0, &label); 186 isc_region_consume(&label, 1); 187 isc_buffer_init(&buffer, owner, sizeof(owner)); 188 if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS) 189 return (ISC_TRUE); 190 191 return (ISC_FALSE); 192 } 193 194 #endif /* RDATA_GENERIC_NSEC3_50_C */ 195