1 /* 2 * edns.c -- EDNS definitions (RFC 2671). 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 11 #include "config.h" 12 13 #include <string.h> 14 #ifdef HAVE_SSL 15 #include <openssl/opensslv.h> 16 #include <openssl/evp.h> 17 #endif 18 19 #include "dns.h" 20 #include "edns.h" 21 #include "nsd.h" 22 #include "query.h" 23 24 #if !defined(HAVE_SSL) || !defined(HAVE_CRYPTO_MEMCMP) 25 /* we need fixed time compare, pull it in from tsig.c */ 26 #define CRYPTO_memcmp memcmp_fixedtime 27 int memcmp_fixedtime(const void *s1, const void *s2, size_t n); 28 #endif 29 30 void 31 edns_init_data(edns_data_type *data, uint16_t max_length) 32 { 33 memset(data, 0, sizeof(edns_data_type)); 34 /* record type: OPT */ 35 data->ok[1] = (TYPE_OPT & 0xff00) >> 8; /* type_hi */ 36 data->ok[2] = TYPE_OPT & 0x00ff; /* type_lo */ 37 /* udp payload size */ 38 data->ok[3] = (max_length & 0xff00) >> 8; /* size_hi */ 39 data->ok[4] = max_length & 0x00ff; /* size_lo */ 40 41 data->error[1] = (TYPE_OPT & 0xff00) >> 8; /* type_hi */ 42 data->error[2] = TYPE_OPT & 0x00ff; /* type_lo */ 43 data->error[3] = (max_length & 0xff00) >> 8; /* size_hi */ 44 data->error[4] = max_length & 0x00ff; /* size_lo */ 45 data->error[5] = 1; /* XXX Extended RCODE=BAD VERS */ 46 47 /* COOKIE OPT HDR */ 48 data->cookie[0] = (COOKIE_CODE & 0xff00) >> 8; 49 data->cookie[1] = (COOKIE_CODE & 0x00ff); 50 data->cookie[2] = (24 & 0xff00) >> 8; 51 data->cookie[3] = (24 & 0x00ff); 52 } 53 54 void 55 edns_init_nsid(edns_data_type *data, uint16_t nsid_len) 56 { 57 /* NSID OPT HDR */ 58 data->nsid[0] = (NSID_CODE & 0xff00) >> 8; 59 data->nsid[1] = (NSID_CODE & 0x00ff); 60 data->nsid[2] = (nsid_len & 0xff00) >> 8; 61 data->nsid[3] = (nsid_len & 0x00ff); 62 } 63 64 void 65 edns_init_record(edns_record_type *edns) 66 { 67 edns->status = EDNS_NOT_PRESENT; 68 edns->position = 0; 69 edns->maxlen = 0; 70 edns->opt_reserved_space = 0; 71 edns->dnssec_ok = 0; 72 edns->nsid = 0; 73 edns->zoneversion = 0; 74 edns->cookie_status = COOKIE_NOT_PRESENT; 75 edns->cookie_len = 0; 76 edns->ede = -1; /* -1 means no Extended DNS Error */ 77 edns->ede_text = NULL; 78 edns->ede_text_len = 0; 79 } 80 81 /** handle a single edns option in the query */ 82 static int 83 edns_handle_option(uint16_t optcode, uint16_t optlen, buffer_type* packet, 84 edns_record_type* edns, struct query* query, nsd_type* nsd) 85 { 86 (void) query; /* in case edns options need the query structure */ 87 /* handle opt code and read the optlen bytes from the packet */ 88 switch(optcode) { 89 case NSID_CODE: 90 /* is NSID enabled? */ 91 if(nsd->nsid_len > 0) { 92 edns->nsid = 1; 93 /* we have to check optlen, and move the buffer along */ 94 buffer_skip(packet, optlen); 95 /* in the reply we need space for optcode+optlen+nsid_bytes */ 96 edns->opt_reserved_space += OPT_HDR + nsd->nsid_len; 97 } else { 98 /* ignore option */ 99 buffer_skip(packet, optlen); 100 } 101 break; 102 case COOKIE_CODE: 103 /* Cookies enabled? */ 104 if(nsd->do_answer_cookie) { 105 if (optlen == 8) 106 edns->cookie_status = COOKIE_INVALID; 107 else if (optlen < 16 || optlen > 40) 108 return 0; /* FORMERR */ 109 else 110 edns->cookie_status = COOKIE_UNVERIFIED; 111 112 edns->cookie_len = optlen; 113 memcpy(edns->cookie, buffer_current(packet), optlen); 114 buffer_skip(packet, optlen); 115 edns->opt_reserved_space += OPT_HDR + 24; 116 } else { 117 buffer_skip(packet, optlen); 118 } 119 break; 120 case ZONEVERSION_CODE: 121 edns->zoneversion = 1; 122 if(optlen > 0) 123 return 0; 124 break; 125 default: 126 buffer_skip(packet, optlen); 127 break; 128 } 129 return 1; 130 } 131 132 int 133 edns_parse_record(edns_record_type *edns, buffer_type *packet, 134 query_type* query, nsd_type* nsd) 135 { 136 /* OPT record type... */ 137 uint8_t opt_owner; 138 uint16_t opt_type; 139 uint16_t opt_class; 140 uint8_t opt_version; 141 uint16_t opt_flags; 142 uint16_t opt_rdlen; 143 144 edns->position = buffer_position(packet); 145 146 if (!buffer_available(packet, (OPT_LEN + OPT_RDATA))) 147 return 0; 148 149 opt_owner = buffer_read_u8(packet); 150 opt_type = buffer_read_u16(packet); 151 if (opt_owner != 0 || opt_type != TYPE_OPT) { 152 /* Not EDNS. */ 153 buffer_set_position(packet, edns->position); 154 return 0; 155 } 156 157 opt_class = buffer_read_u16(packet); 158 (void)buffer_read_u8(packet); /* opt_extended_rcode */ 159 opt_version = buffer_read_u8(packet); 160 opt_flags = buffer_read_u16(packet); 161 opt_rdlen = buffer_read_u16(packet); 162 163 if (opt_version != 0) { 164 /* The only error is VERSION not implemented */ 165 edns->status = EDNS_ERROR; 166 return 1; 167 } 168 169 if (opt_rdlen > 0) { 170 if(!buffer_available(packet, opt_rdlen)) 171 return 0; 172 if(opt_rdlen > 65530) 173 return 0; 174 /* there is more to come, read opt code */ 175 while(opt_rdlen >= 4) { 176 uint16_t optcode = buffer_read_u16(packet); 177 uint16_t optlen = buffer_read_u16(packet); 178 opt_rdlen -= 4; 179 if(opt_rdlen < optlen) 180 return 0; /* opt too long, formerr */ 181 opt_rdlen -= optlen; 182 if(!edns_handle_option(optcode, optlen, packet, 183 edns, query, nsd)) 184 return 0; 185 } 186 if(opt_rdlen != 0) 187 return 0; 188 } 189 190 edns->status = EDNS_OK; 191 edns->maxlen = opt_class; 192 edns->dnssec_ok = opt_flags & DNSSEC_OK_MASK; 193 return 1; 194 } 195 196 size_t 197 edns_reserved_space(edns_record_type *edns) 198 { 199 /* MIEK; when a pkt is too large?? */ 200 return edns->status == EDNS_NOT_PRESENT ? 0 201 : (OPT_LEN + OPT_RDATA + edns->opt_reserved_space); 202 } 203 204 int siphash(const uint8_t *in, const size_t inlen, 205 const uint8_t *k, uint8_t *out, const size_t outlen); 206 207 /** RFC 1982 comparison, uses unsigned integers, and tries to avoid 208 * compiler optimization (eg. by avoiding a-b<0 comparisons), 209 * this routine matches compare_serial(), for SOA serial number checks */ 210 static int 211 compare_1982(uint32_t a, uint32_t b) 212 { 213 /* for 32 bit values */ 214 const uint32_t cutoff = ((uint32_t) 1 << (32 - 1)); 215 216 if (a == b) { 217 return 0; 218 } else if ((a < b && b - a < cutoff) || (a > b && a - b > cutoff)) { 219 return -1; 220 } else { 221 return 1; 222 } 223 } 224 225 /** if we know that b is larger than a, return the difference between them, 226 * that is the distance between them. in RFC1982 arith */ 227 static uint32_t 228 subtract_1982(uint32_t a, uint32_t b) 229 { 230 /* for 32 bit values */ 231 const uint32_t cutoff = ((uint32_t) 1 << (32 - 1)); 232 233 if(a == b) 234 return 0; 235 if(a < b && b - a < cutoff) { 236 return b-a; 237 } 238 if(a > b && a - b > cutoff) { 239 return ((uint32_t)0xffffffff) - (a-b-1); 240 } 241 /* wrong case, b smaller than a */ 242 return 0; 243 } 244 245 void cookie_verify(query_type *q, struct nsd* nsd, uint32_t *now_p) { 246 uint8_t hash[8], hash2verify[8]; 247 uint32_t cookie_time, now_uint32; 248 size_t verify_size; 249 int i; 250 251 /* We support only draft-sury-toorop-dnsop-server-cookies sizes */ 252 if(q->edns.cookie_len != 24) 253 return; 254 255 if(q->edns.cookie[8] != 1) 256 return; 257 258 q->edns.cookie_status = COOKIE_INVALID; 259 260 cookie_time = (q->edns.cookie[12] << 24) 261 | (q->edns.cookie[13] << 16) 262 | (q->edns.cookie[14] << 8) 263 | q->edns.cookie[15]; 264 265 now_uint32 = *now_p ? *now_p : (*now_p = (uint32_t)time(NULL)); 266 267 if(compare_1982(now_uint32, cookie_time) > 0) { 268 /* ignore cookies > 1 hour in past */ 269 if (subtract_1982(cookie_time, now_uint32) > 3600) 270 return; 271 } else if (subtract_1982(now_uint32, cookie_time) > 300) { 272 /* ignore cookies > 5 minutes in future */ 273 return; 274 } 275 276 memcpy(hash2verify, q->edns.cookie + 16, 8); 277 278 #ifdef INET6 279 if(q->client_addr.ss_family == AF_INET6) { 280 memcpy(q->edns.cookie + 16, &((struct sockaddr_in6 *)&q->client_addr)->sin6_addr, 16); 281 verify_size = 32; 282 } else { 283 memcpy(q->edns.cookie + 16, &((struct sockaddr_in *)&q->client_addr)->sin_addr, 4); 284 verify_size = 20; 285 } 286 #else 287 memcpy( q->edns.cookie + 16, &q->client_addr.sin_addr, 4); 288 verify_size = 20; 289 #endif 290 291 q->edns.cookie_status = COOKIE_INVALID; 292 siphash(q->edns.cookie, verify_size, 293 nsd->cookie_secrets[0].cookie_secret, hash, 8); 294 if(CRYPTO_memcmp(hash2verify, hash, 8) == 0 ) { 295 if (subtract_1982(cookie_time, now_uint32) < 1800) { 296 q->edns.cookie_status = COOKIE_VALID_REUSE; 297 memcpy(q->edns.cookie + 16, hash, 8); 298 } else 299 q->edns.cookie_status = COOKIE_VALID; 300 return; 301 } 302 for(i = 1; 303 i < (int)nsd->cookie_count && i < NSD_COOKIE_HISTORY_SIZE; 304 i++) { 305 siphash(q->edns.cookie, verify_size, 306 nsd->cookie_secrets[i].cookie_secret, hash, 8); 307 if(CRYPTO_memcmp(hash2verify, hash, 8) == 0 ) { 308 q->edns.cookie_status = COOKIE_VALID; 309 return; 310 } 311 } 312 } 313 314 void cookie_create(query_type *q, struct nsd* nsd, uint32_t *now_p) 315 { 316 uint8_t hash[8]; 317 uint32_t now_uint32; 318 319 if (q->edns.cookie_status == COOKIE_VALID_REUSE) 320 return; 321 322 now_uint32 = *now_p ? *now_p : (*now_p = (uint32_t)time(NULL)); 323 q->edns.cookie[ 8] = 1; 324 q->edns.cookie[ 9] = 0; 325 q->edns.cookie[10] = 0; 326 q->edns.cookie[11] = 0; 327 q->edns.cookie[12] = (now_uint32 & 0xFF000000) >> 24; 328 q->edns.cookie[13] = (now_uint32 & 0x00FF0000) >> 16; 329 q->edns.cookie[14] = (now_uint32 & 0x0000FF00) >> 8; 330 q->edns.cookie[15] = now_uint32 & 0x000000FF; 331 #ifdef INET6 332 if (q->client_addr.ss_family == AF_INET6) { 333 memcpy( q->edns.cookie + 16 334 , &((struct sockaddr_in6 *)&q->client_addr)->sin6_addr, 16); 335 siphash(q->edns.cookie, 32, nsd->cookie_secrets[0].cookie_secret, hash, 8); 336 } else { 337 memcpy( q->edns.cookie + 16 338 , &((struct sockaddr_in *)&q->client_addr)->sin_addr, 4); 339 siphash(q->edns.cookie, 20, nsd->cookie_secrets[0].cookie_secret, hash, 8); 340 } 341 #else 342 memcpy( q->edns.cookie + 16, &q->client_addr.sin_addr, 4); 343 siphash(q->edns.cookie, 20, nsd->cookie_secrets[0].cookie_secret, hash, 8); 344 #endif 345 memcpy(q->edns.cookie + 16, hash, 8); 346 } 347 348