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