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: naptr_35.c,v 1.12 2020/02/26 18:47:59 florian Exp $ */ 18 19 /* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */ 20 21 /* RFC2915 */ 22 23 #ifndef RDATA_GENERIC_NAPTR_35_C 24 #define RDATA_GENERIC_NAPTR_35_C 25 26 #include <isc/regex.h> 27 28 /* 29 * Check the wire format of the Regexp field. 30 * Don't allow embeded NUL's. 31 */ 32 static inline isc_result_t 33 txt_valid_regex(const unsigned char *txt) { 34 unsigned int nsub = 0; 35 char regex[256]; 36 char *cp; 37 isc_boolean_t flags = ISC_FALSE; 38 isc_boolean_t replace = ISC_FALSE; 39 unsigned char c; 40 unsigned char delim; 41 unsigned int len; 42 int n; 43 44 len = *txt++; 45 if (len == 0U) 46 return (ISC_R_SUCCESS); 47 48 delim = *txt++; 49 len--; 50 51 /* 52 * Digits, backslash and flags can't be delimiters. 53 */ 54 switch (delim) { 55 case '0': case '1': case '2': case '3': case '4': 56 case '5': case '6': case '7': case '8': case '9': 57 case '\\': case 'i': case 0: 58 return (DNS_R_SYNTAX); 59 } 60 61 cp = regex; 62 while (len-- > 0) { 63 c = *txt++; 64 if (c == 0) 65 return (DNS_R_SYNTAX); 66 if (c == delim && !replace) { 67 replace = ISC_TRUE; 68 continue; 69 } else if (c == delim && !flags) { 70 flags = ISC_TRUE; 71 continue; 72 } else if (c == delim) 73 return (DNS_R_SYNTAX); 74 /* 75 * Flags are not escaped. 76 */ 77 if (flags) { 78 switch (c) { 79 case 'i': 80 continue; 81 default: 82 return (DNS_R_SYNTAX); 83 } 84 } 85 if (!replace) 86 *cp++ = c; 87 if (c == '\\') { 88 if (len == 0) 89 return (DNS_R_SYNTAX); 90 c = *txt++; 91 if (c == 0) 92 return (DNS_R_SYNTAX); 93 len--; 94 if (replace) 95 switch (c) { 96 case '0': return (DNS_R_SYNTAX); 97 case '1': if (nsub < 1) nsub = 1; break; 98 case '2': if (nsub < 2) nsub = 2; break; 99 case '3': if (nsub < 3) nsub = 3; break; 100 case '4': if (nsub < 4) nsub = 4; break; 101 case '5': if (nsub < 5) nsub = 5; break; 102 case '6': if (nsub < 6) nsub = 6; break; 103 case '7': if (nsub < 7) nsub = 7; break; 104 case '8': if (nsub < 8) nsub = 8; break; 105 case '9': if (nsub < 9) nsub = 9; break; 106 } 107 if (!replace) 108 *cp++ = c; 109 } 110 } 111 if (!flags) 112 return (DNS_R_SYNTAX); 113 *cp = '\0'; 114 n = isc_regex_validate(regex); 115 if (n < 0 || nsub > (unsigned int)n) 116 return (DNS_R_SYNTAX); 117 return (ISC_R_SUCCESS); 118 } 119 120 static inline isc_result_t 121 totext_naptr(ARGS_TOTEXT) { 122 isc_region_t region; 123 dns_name_t name; 124 dns_name_t prefix; 125 isc_boolean_t sub; 126 char buf[sizeof("64000")]; 127 unsigned short num; 128 129 REQUIRE(rdata->type == dns_rdatatype_naptr); 130 REQUIRE(rdata->length != 0); 131 132 dns_name_init(&name, NULL); 133 dns_name_init(&prefix, NULL); 134 135 dns_rdata_toregion(rdata, ®ion); 136 137 /* 138 * Order. 139 */ 140 num = uint16_fromregion(®ion); 141 isc_region_consume(®ion, 2); 142 snprintf(buf, sizeof(buf), "%u", num); 143 RETERR(isc_str_tobuffer(buf, target)); 144 RETERR(isc_str_tobuffer(" ", target)); 145 146 /* 147 * Preference. 148 */ 149 num = uint16_fromregion(®ion); 150 isc_region_consume(®ion, 2); 151 snprintf(buf, sizeof(buf), "%u", num); 152 RETERR(isc_str_tobuffer(buf, target)); 153 RETERR(isc_str_tobuffer(" ", target)); 154 155 /* 156 * Flags. 157 */ 158 RETERR(txt_totext(®ion, ISC_TRUE, target)); 159 RETERR(isc_str_tobuffer(" ", target)); 160 161 /* 162 * Service. 163 */ 164 RETERR(txt_totext(®ion, ISC_TRUE, target)); 165 RETERR(isc_str_tobuffer(" ", target)); 166 167 /* 168 * Regexp. 169 */ 170 RETERR(txt_totext(®ion, ISC_TRUE, target)); 171 RETERR(isc_str_tobuffer(" ", target)); 172 173 /* 174 * Replacement. 175 */ 176 dns_name_fromregion(&name, ®ion); 177 sub = name_prefix(&name, tctx->origin, &prefix); 178 return (dns_name_totext(&prefix, sub, target)); 179 } 180 181 static inline isc_result_t 182 fromwire_naptr(ARGS_FROMWIRE) { 183 dns_name_t name; 184 isc_region_t sr; 185 unsigned char *regex; 186 187 REQUIRE(type == dns_rdatatype_naptr); 188 189 UNUSED(type); 190 UNUSED(rdclass); 191 192 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 193 194 dns_name_init(&name, NULL); 195 196 /* 197 * Order, preference. 198 */ 199 isc_buffer_activeregion(source, &sr); 200 if (sr.length < 4) 201 return (ISC_R_UNEXPECTEDEND); 202 RETERR(isc_mem_tobuffer(target, sr.base, 4)); 203 isc_buffer_forward(source, 4); 204 205 /* 206 * Flags. 207 */ 208 RETERR(txt_fromwire(source, target)); 209 210 /* 211 * Service. 212 */ 213 RETERR(txt_fromwire(source, target)); 214 215 /* 216 * Regexp. 217 */ 218 regex = isc_buffer_used(target); 219 RETERR(txt_fromwire(source, target)); 220 RETERR(txt_valid_regex(regex)); 221 222 /* 223 * Replacement. 224 */ 225 return (dns_name_fromwire(&name, source, dctx, options, target)); 226 } 227 228 static inline isc_result_t 229 towire_naptr(ARGS_TOWIRE) { 230 dns_name_t name; 231 dns_offsets_t offsets; 232 isc_region_t sr; 233 234 REQUIRE(rdata->type == dns_rdatatype_naptr); 235 REQUIRE(rdata->length != 0); 236 237 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); 238 /* 239 * Order, preference. 240 */ 241 dns_rdata_toregion(rdata, &sr); 242 RETERR(isc_mem_tobuffer(target, sr.base, 4)); 243 isc_region_consume(&sr, 4); 244 245 /* 246 * Flags. 247 */ 248 RETERR(isc_mem_tobuffer(target, sr.base, sr.base[0] + 1)); 249 isc_region_consume(&sr, sr.base[0] + 1); 250 251 /* 252 * Service. 253 */ 254 RETERR(isc_mem_tobuffer(target, sr.base, sr.base[0] + 1)); 255 isc_region_consume(&sr, sr.base[0] + 1); 256 257 /* 258 * Regexp. 259 */ 260 RETERR(isc_mem_tobuffer(target, sr.base, sr.base[0] + 1)); 261 isc_region_consume(&sr, sr.base[0] + 1); 262 263 /* 264 * Replacement. 265 */ 266 dns_name_init(&name, offsets); 267 dns_name_fromregion(&name, &sr); 268 return (dns_name_towire(&name, cctx, target)); 269 } 270 271 #endif /* RDATA_GENERIC_NAPTR_35_C */ 272