1 /* srp-dns-proxy.c 2 * 3 * Copyright (c) 2018-2021 Apple Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * https://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 * This is a DNSSD Service Registration Protocol gateway. The purpose of this is to make it possible 18 * for SRP clients to update DNS servers that don't support SRP. 19 * 20 * The way it works is that this gateway listens on port ANY:53 and forwards either to another port on 21 * the same host (not recommended) or to any port (usually 53) on a different host. Requests are accepted 22 * over both TCP and UDP in principle, but UDP requests should be from constrained nodes, and rely on 23 * network topology for authentication. 24 * 25 * Note that this is not a full DNS proxy, so you can't just put it in front of a DNS server. 26 */ 27 28 // Get DNS server IP address 29 // Get list of permitted source subnets for TCP updates 30 // Get list of permitted source subnet/interface tuples for UDP updates 31 // Set up UDP listener 32 // Set up TCP listener (no TCP Fast Open) 33 // Event loop 34 // Transaction processing: 35 // 1. If UDP, validate that it's from a subnet that is valid for the interface on which it was received. 36 // 2. If TCP, validate that it's from a permitted subnet 37 // 3. Check that the message is a valid SRP update according to the rules 38 // 4. Check the signature 39 // 5. Do a DNS Update with prerequisites to prevent overwriting a host record with the same owner name but 40 // a different key. 41 // 6. Send back the response 42 43 #define __APPLE_USE_RFC_3542 44 45 #include <stdlib.h> 46 #include <string.h> 47 #include <stdio.h> 48 #include <unistd.h> 49 #include <errno.h> 50 #include <sys/socket.h> 51 #include <netinet/in.h> 52 #include <arpa/inet.h> 53 #include <fcntl.h> 54 #include <sys/time.h> 55 #include <dns_sd.h> 56 57 #include "srp.h" 58 #include "dns-msg.h" 59 #include "srp-crypto.h" 60 #include "ioloop.h" 61 #include "srp-gw.h" 62 #include "config-parse.h" 63 #include "srp-proxy.h" 64 65 static addr_t dns_server; 66 static dns_name_t *service_update_zone; // The zone to update when we receive an update for default.service.arpa. 67 static hmac_key_t *key; 68 69 static int 70 usage(const char *progname) 71 { 72 ERROR("usage: %s -s <addr> <port> -k <key-file> -t <subnet> ... -u <ifname> <subnet> ...", progname); 73 ERROR(" -s can only appear once."); 74 ERROR(" -k can appear once."); 75 ERROR(" -t can only appear once, and is followed by one or more subnets."); 76 ERROR(" -u can appear more than once, is followed by one interface name, and"); 77 ERROR(" one or more subnets."); 78 ERROR(" <addr> is an IPv4 address or IPv6 address."); 79 ERROR(" <port> is a UDP port number."); 80 ERROR(" <key-file> is a file containing an HMAC-SHA256 key for authenticating updates to the auth server."); 81 ERROR(" <subnet> is an IP address followed by a slash followed by the prefix width."); 82 ERROR(" <ifname> is the printable name of the interface."); 83 ERROR("ex: srp-gw -s 2001:DB8::1 53 -k srp.key -t 2001:DB8:1300::/48 -u en0 2001:DB8:1300:1100::/56"); 84 return 1; 85 } 86 87 // Free the data structures into which the SRP update was parsed. The pointers to the various DNS objects that these 88 // structures point to are owned by the parsed DNS message, and so these do not need to be freed here. 89 void 90 update_free_parts(service_instance_t *service_instances, service_instance_t *added_instances, 91 service_t *services, dns_host_description_t *host_description) 92 { 93 service_instance_t *sip; 94 service_t *sp; 95 96 for (sip = service_instances; sip; ) { 97 service_instance_t *next = sip->next; 98 free(sip); 99 sip = next; 100 } 101 for (sip = added_instances; sip; ) { 102 service_instance_t *next = sip->next; 103 free(sip); 104 sip = next; 105 } 106 for (sp = services; sp; ) { 107 service_t *next = sp->next; 108 free(sp); 109 sp = next; 110 } 111 if (host_description != NULL) { 112 free(host_description); 113 } 114 } 115 116 // Free all the stuff that we accumulated while processing the SRP update. 117 void 118 update_free(update_t *update) 119 { 120 // Free all of the structures we collated RRs into: 121 update_free_parts(update->instances, update->added_instances, update->services, update->host); 122 // We don't need to free the zone name: it's either borrowed from the message, 123 // or it's service_update_zone, which is static. 124 message_free(update->message); 125 dns_message_free(update->parsed_message); 126 free(update); 127 } 128 129 130 #define name_to_wire(towire, name) name_to_wire_(towire, name, __LINE__) 131 void 132 name_to_wire_(dns_towire_state_t *towire, dns_name_t *name, int line) 133 { 134 // Does compression... 135 dns_concatenate_name_to_wire_(towire, name, NULL, NULL, line); 136 } 137 138 void 139 rdata_to_wire(dns_towire_state_t *towire, dns_rr_t *rr) 140 { 141 dns_rdlength_begin(towire); 142 143 // These are the only types we expect to see. If something else were passed, it would be written as rdlen=0. 144 switch(rr->type) { 145 case dns_rrtype_ptr: 146 name_to_wire(towire, rr->data.ptr.name); 147 break; 148 149 case dns_rrtype_srv: 150 dns_u16_to_wire(towire, rr->data.srv.priority); 151 dns_u16_to_wire(towire, rr->data.srv.weight); 152 dns_u16_to_wire(towire, rr->data.srv.port); 153 name_to_wire(towire, rr->data.srv.name); 154 break; 155 156 case dns_rrtype_txt: 157 dns_rdata_raw_data_to_wire(towire, rr->data.txt.data, rr->data.txt.len); 158 break; 159 160 case dns_rrtype_key: 161 dns_u16_to_wire(towire, rr->data.key.flags); 162 dns_u8_to_wire(towire, rr->data.key.protocol); 163 dns_u8_to_wire(towire, rr->data.key.algorithm); 164 dns_rdata_raw_data_to_wire(towire, rr->data.key.key, rr->data.key.len); 165 break; 166 167 case dns_rrtype_a: 168 dns_rdata_raw_data_to_wire(towire, &rr->data.a, sizeof rr->data.a); 169 break; 170 171 case dns_rrtype_aaaa: 172 dns_rdata_raw_data_to_wire(towire, &rr->data.aaaa, sizeof rr->data.aaaa); 173 break; 174 } 175 176 dns_rdlength_end(towire); 177 } 178 179 // We only list the types we are using--there are other types that we don't support. 180 typedef enum prereq_type prereq_type_t; 181 enum prereq_type { 182 update_rrset_equals, // RFC 2136 section 2.4.2: RRset Exists (Value Dependent) 183 update_name_not_in_use, // RFC 2136 section 2.4.5: Name Is Not In Use 184 }; 185 186 void 187 add_prerequisite(dns_wire_t *msg, dns_towire_state_t *towire, prereq_type_t ptype, dns_name_t *name, dns_rr_t *rr) 188 { 189 char namebuf[DNS_MAX_NAME_SIZE + 1]; 190 if (ntohs(msg->nscount) != 0 || ntohs(msg->arcount) != 0) { 191 ERROR("%s: adding prerequisite after updates", dns_name_print(name, namebuf, sizeof namebuf)); 192 towire->truncated = true; 193 } 194 name_to_wire(towire, name); 195 switch(ptype) { 196 case update_rrset_equals: 197 dns_u16_to_wire(towire, rr->type); 198 dns_u16_to_wire(towire, rr->qclass); 199 dns_ttl_to_wire(towire, 0); 200 rdata_to_wire(towire, rr); 201 break; 202 case update_name_not_in_use: 203 dns_u16_to_wire(towire, dns_rrtype_any); // TYPE 204 dns_u16_to_wire(towire, dns_qclass_none); // CLASS 205 dns_ttl_to_wire(towire, 0); // TTL 206 dns_u16_to_wire(towire, 0); // RDLEN 207 break; 208 } 209 msg->ancount = htons(ntohs(msg->ancount) + 1); 210 } 211 212 // We actually only support one type of delete, so it's a bit silly to specify it, but in principle we might 213 // want more later. 214 typedef enum delete_type delete_type_t; 215 enum delete_type { 216 delete_name, // RFC 2136 section 2.5.3: Delete all RRsets from a name 217 }; 218 219 void 220 add_delete(dns_wire_t *msg, dns_towire_state_t *towire, delete_type_t dtype, dns_name_t *name) 221 { 222 name_to_wire(towire, name); 223 switch(dtype) { 224 case delete_name: 225 dns_u16_to_wire(towire, dns_rrtype_any); // TYPE 226 dns_u16_to_wire(towire, dns_qclass_any); // CLASS 227 dns_ttl_to_wire(towire, 0); // TTL 228 dns_u16_to_wire(towire, 0); // RDLEN 229 break; 230 } 231 msg->nscount = htons(ntohs(msg->nscount) + 1); 232 } 233 234 // Copy the RR we received in the SRP update out in wire format. 235 236 void 237 add_rr(dns_wire_t *msg, dns_towire_state_t *towire, dns_name_t *name, dns_rr_t *rr) 238 { 239 if (rr != NULL) { 240 name_to_wire(towire, name); 241 dns_u16_to_wire(towire, rr->type); // TYPE 242 dns_u16_to_wire(towire, rr->qclass); // CLASS 243 dns_ttl_to_wire(towire, rr->ttl); // TTL 244 rdata_to_wire(towire, rr); // RDLEN 245 msg->nscount = htons(ntohs(msg->nscount) + 1); 246 } 247 } 248 249 // Construct an update of the specified type, assuming that the record being updated 250 // either exists or does not exist, depending on the value of exists. Actual records 251 // to be update are taken from the update_t. 252 // 253 // Analysis: 254 // 255 // The goal of the update is to either bring the zone to the state described in the SRP update, or 256 // determine that the state described in the SRP update conflicts with what is already present in 257 // the zone. 258 // 259 // Possible scenarios: 260 // 1. Update and Zone are the same (A and AAAA records may differ): 261 // Prerequisites: 262 // a. for each instance: KEY RR exists on instance name and is the same 263 // b. for host: KEY RR exists on host name and is the same 264 // Update: 265 // a. for each instance: delete all records on instance name, add KEY RR, add SRV RR, add TXT RR 266 // b. for host: delete host instance, add A, AAAA and KEY RRs 267 // c. for each service: add PTR record pointing on service name to service instance name 268 // 269 // We should try 1 first, because it should be the steady state case; that is, it should be what happens 270 // most of the time. 271 // If 1 fails, then we could have some service instances present and others not. There is no way to 272 // know without trying. We can at this point either try to add each service instance in a separate update, 273 // or assume that none are present and add them all at once, and then if this fails add them individually. 274 // I think that it makes sense to try them all first, because that should be the second most common case: 275 // 276 // 2. Nothing in update is present in zone: 277 // Prerequisites: 278 // a. For each instance: instance name is not in use 279 // b. Host name is not in use 280 // Update: 281 // a. for each instance: add KEY RR, add SRV RR, add TXT RR on instance name 282 // b. for host: add A, AAAA and KEY RRs on host name 283 // c. for each service: add PTR record pointing on service name to service instance name 284 // 285 // If either (1) or (2) works, we're done. If both fail, then we need to do the service instance updates 286 // and host update one by one. This is a bit nasty because we actually have to try twice: once assuming 287 // the RR exists, and once assuming it doesn't. If any of the instance updates fail, or the host update 288 // fails, we delete all the ones that succeeded. 289 // 290 // In the cases other than (1) and (2), we can add all the service PTRs in the host update, because they're 291 // only added if the host update succeeds; if it fails, we have to go back and remove all the service 292 // instances. 293 // 294 // One open question for the SRP document: we probably want to signal whether the conflict is with the 295 // hostname or one of the service instance names. We can do this with an EDNS(0) option. 296 // 297 // The flow will be: 298 // - Try to update assuming everything is there already (case 1) 299 // - Try to update assuming nothing is there already (case 2) 300 // - For each service instance: 301 // - Try to update assuming it's not there; if this succeeds, add this instance to the list of 302 // instances that have been added. If not: 303 // - Try to update assuming it is there 304 // - If this fails, go to fail 305 // - Try to update the host (and also services) assuming the host is not there. If this fails: 306 // - Try to update the host (and also services) assuming the host is there. If this succeeds: 307 // - return success 308 // fail: 309 // - For each service instance in the list of instances that have been added: 310 // - delete all records on the instance name. 311 // 312 // One thing that isn't accounted for here: it's possible that a previous update added some but not all 313 // instances in the current update. Subsequently, some other device may have claimed an instance that is 314 // present but in conflict in the current update. In this case, all of the instances prior to that one 315 // in the update will actually have been updated by this update, but then the update as a whole will fail. 316 // I think this is unlikely to be an actual problem, and there's no way to address it without a _lot_ of 317 // complexity. 318 319 bool 320 construct_update(update_t *update) 321 { 322 dns_towire_state_t towire; 323 dns_wire_t *msg = update->update; // Solely to reduce the amount of typing. 324 service_instance_t *instance; 325 service_t *service; 326 host_addr_t *host_addr; 327 328 // Set up the message constructor 329 memset(&towire, 0, sizeof towire); 330 towire.p = &msg->data[0]; // We start storing RR data here. 331 towire.lim = &msg->data[0] + update->update_max; // This is the limit to how much we can store. 332 towire.message = msg; 333 334 // Initialize the update message... 335 memset(msg, 0, DNS_HEADER_SIZE); 336 dns_qr_set(msg, dns_qr_query); 337 dns_opcode_set(msg, dns_opcode_update); 338 msg->id = srp_random16(); 339 340 // An update always has one question, which is the zone name. 341 msg->qdcount = htons(1); 342 name_to_wire(&towire, update->zone_name); 343 dns_u16_to_wire(&towire, dns_rrtype_soa); 344 dns_u16_to_wire(&towire, dns_qclass_in); 345 346 switch(update->state) { 347 case connect_to_server: 348 ERROR("Update construction requested when still connecting."); 349 update->update_length = 0; 350 return false; 351 352 // Do a DNS Update for a service instance 353 case refresh_existing: 354 // Add a "KEY exists and is <x> and a PTR exists and is <x> prerequisite for each instance being updated. 355 for (instance = update->instances; instance; instance = instance->next) { 356 add_prerequisite(msg, &towire, update_rrset_equals, instance->name, update->host->key); 357 } 358 add_prerequisite(msg, &towire, update_rrset_equals, update->host->name, update->host->key); 359 // Now add a delete for each service instance 360 for (instance = update->instances; instance; instance = instance->next) { 361 add_delete(msg, &towire, delete_name, instance->name); 362 } 363 add_delete(msg, &towire, delete_name, update->host->name); 364 365 add_instances: 366 // Now add the update for each instance. 367 for (instance = update->instances; instance; instance = instance->next) { 368 add_rr(msg, &towire, instance->name, update->host->key); 369 add_rr(msg, &towire, instance->name, instance->srv); 370 add_rr(msg, &towire, instance->name, instance->txt); 371 } 372 // Add the update for each service 373 for (service = update->services; service; service = service->next) { 374 add_rr(msg, &towire, service->rr->name, service->rr); 375 } 376 // Add the host records... 377 add_rr(msg, &towire, update->host->name, update->host->key); 378 for (host_addr = update->host->addrs; host_addr; host_addr = host_addr->next) { 379 add_rr(msg, &towire, update->host->name, &host_addr->rr); 380 } 381 break; 382 383 case create_nonexistent: 384 // Add a "name not in use" prerequisite for each instance being updated. 385 for (instance = update->instances; instance; instance = instance->next) { 386 add_prerequisite(msg, &towire, update_name_not_in_use, instance->name, (dns_rr_t *)NULL); 387 } 388 add_prerequisite(msg, &towire, update_name_not_in_use, update->host->name, (dns_rr_t *)NULL); 389 goto add_instances; 390 391 case create_nonexistent_instance: 392 // The only prerequisite is that this specific service instance doesn't exist. 393 add_prerequisite(msg, &towire, update_name_not_in_use, update->instance->name, (dns_rr_t *)NULL); 394 goto add_instance; 395 396 case refresh_existing_instance: 397 // If instance already exists, prerequisite is that it has the same key, and we also have to 398 // delete all RRs on the name before adding our RRs, in case they have changed. 399 add_prerequisite(msg, &towire, update_rrset_equals, update->instance->name, update->host->key); 400 add_delete(msg, &towire, delete_name, update->instance->name); 401 add_instance: 402 add_rr(msg, &towire, update->instance->name, update->host->key); 403 add_rr(msg, &towire, update->instance->name, update->instance->srv); 404 add_rr(msg, &towire, update->instance->name, update->instance->txt); 405 break; 406 407 case create_nonexistent_host: 408 add_prerequisite(msg, &towire, update_name_not_in_use, update->host->name, (dns_rr_t *)NULL); 409 goto add_host; 410 411 case refresh_existing_host: 412 add_prerequisite(msg, &towire, update_rrset_equals, update->host->name, update->host->key); 413 add_delete(msg, &towire, delete_name, update->host->name); 414 // Add the service PTRs here--these don't need to be in a separate update, because if we get here 415 // the only thing that can make adding them not okay is if adding the host fails. 416 // Add the update for each service 417 for (service = update->services; service; service = service->next) { 418 add_rr(msg, &towire, service->rr->name, service->rr); 419 } 420 add_host: 421 // Add the host records... 422 add_rr(msg, &towire, update->host->name, update->host->key); 423 for (host_addr = update->host->addrs; host_addr; host_addr = host_addr->next) { 424 add_rr(msg, &towire, update->host->name, &host_addr->rr); 425 } 426 break; 427 428 case delete_failed_instance: 429 // Delete all the instances we successfull added before discovering a problem. 430 // It is possible in principle that these could have been overwritten by some other 431 // process and we could be deleting the wrong stuff, but in practice this should 432 // never happen if these are legitimately managed by SRP. Once a name has been 433 // claimed by SRP, it should continue to be managed by SRP until its lease expires 434 // and SRP deletes it, at which point it is of course fair game. 435 for (instance = update->instances; instance; instance = instance->next) { 436 add_delete(msg, &towire, delete_name, instance->name); 437 } 438 break; 439 } 440 if (towire.error != 0) { 441 ERROR("construct_update: error %s while generating update at line %d", strerror(towire.error), towire.line); 442 return false; 443 } 444 update->update_length = towire.p - (uint8_t *)msg; 445 return true; 446 } 447 448 void 449 update_finished(update_t *update, int rcode) 450 { 451 comm_t *comm = update->client; 452 struct iovec iov; 453 dns_wire_t response; 454 INFO("Update Finished, rcode = " PUB_S_SRP, dns_rcode_name(rcode)); 455 456 memset(&response, 0, DNS_HEADER_SIZE); 457 response.id = update->message->wire.id; 458 response.bitfield = update->message->wire.bitfield; 459 dns_rcode_set(&response, rcode); 460 dns_qr_set(&response, dns_qr_response); 461 462 iov.iov_base = &response; 463 iov.iov_len = DNS_HEADER_SIZE; 464 465 comm->send_response(comm, update->message, &iov, 1); 466 467 // If success, construct a response 468 // If fail, send a quick status code 469 // Signal host name conflict and instance name conflict using different rcodes (?) 470 // Okay, so if there's a host name/instance name conflict, and the host name has the right key, then 471 // the instance name is actually bogus and should be overwritten. 472 // If the host has the wrong key, and the instance is present, then the instance is also bogus. 473 // So in each of these cases, perhaps we should just gc the instance. 474 // This would mean that there is nothing to signal: either the instance is a mismatch, and we 475 // overwrite it and return success, or the host is a mismatch and we gc the instance and return failure. 476 ioloop_close(&update->server->io); 477 update_free(update); 478 } 479 480 void 481 update_send(update_t *update) 482 { 483 struct iovec iov[4]; 484 dns_towire_state_t towire; 485 dns_wire_t *msg = update->update; 486 struct timeval tv; 487 uint8_t *p_mac; 488 #ifdef DEBUG_DECODE_UPDATE 489 dns_message_t *decoded; 490 #endif 491 492 // Set up the message constructor 493 memset(&towire, 0, sizeof towire); 494 towire.p = (uint8_t *)msg + update->update_length; // We start storing RR data here. 495 towire.lim = &msg->data[0] + update->update_max; // This is the limit to how much we can store. 496 towire.message = msg; 497 towire.p_rdlength = NULL; 498 towire.p_opt = NULL; 499 500 // If we have a key, sign the message with the key using TSIG HMAC-SHA256. 501 if (key != NULL) { 502 // Maintain an IOV with the bits of the message that we need to sign. 503 iov[0].iov_base = msg; 504 505 name_to_wire(&towire, key->name); 506 iov[0].iov_len = towire.p - (uint8_t *)iov[0].iov_base; 507 dns_u16_to_wire(&towire, dns_rrtype_tsig); // RRTYPE 508 iov[1].iov_base = towire.p; 509 dns_u16_to_wire(&towire, dns_qclass_any); // CLASS 510 dns_ttl_to_wire(&towire, 0); // TTL 511 iov[1].iov_len = towire.p - (uint8_t *)iov[1].iov_base; 512 // The message digest skips the RDLEN field. 513 dns_rdlength_begin(&towire); // RDLEN 514 iov[2].iov_base = towire.p; 515 dns_full_name_to_wire(NULL, &towire, "hmac-sha256."); // Algorithm Name 516 gettimeofday(&tv, NULL); 517 dns_u48_to_wire(&towire, tv.tv_sec); // Time since epoch 518 dns_u16_to_wire(&towire, 300); // Fudge interval 519 // (clocks can be skewed by up to 5 minutes) 520 // Message digest doesn't cover MAC size or MAC fields, for obvious reasons, nor original message ID. 521 iov[2].iov_len = towire.p - (uint8_t *)iov[2].iov_base; 522 dns_u16_to_wire(&towire, SRP_SHA256_DIGEST_SIZE); // MAC Size 523 p_mac = towire.p; // MAC 524 if (!towire.error) { 525 if (towire.p + SRP_SHA256_DIGEST_SIZE >= towire.lim) { 526 towire.error = ENOBUFS; 527 towire.truncated = true; 528 towire.line = __LINE__; 529 } else { 530 towire.p += SRP_SHA256_DIGEST_SIZE; 531 } 532 } 533 // We have to copy the message ID into the tsig signature; this is because in some cases, although not this one, 534 // the message ID will be overwritten. So the copy of the ID is what's validated, but it's copied into the 535 // header for validation, so we don't include it when generating the hash. 536 dns_rdata_raw_data_to_wire(&towire, &msg->id, sizeof msg->id); 537 iov[3].iov_base = towire.p; 538 dns_u16_to_wire(&towire, 0); // TSIG Error (always 0 on send). 539 dns_u16_to_wire(&towire, 0); // Other Len (MBZ?) 540 iov[3].iov_len = towire.p - (uint8_t *)iov[3].iov_base; 541 dns_rdlength_end(&towire); 542 543 // Okay, we have stored the TSIG signature, now compute the message digest. 544 srp_hmac_iov(key, p_mac, SRP_SHA256_DIGEST_SIZE, &iov[0], 4); 545 msg->arcount = htons(ntohs(msg->arcount) + 1); 546 update->update_length = towire.p - (const uint8_t *)msg; 547 } 548 549 if (towire.error != 0) { 550 ERROR("update_send: error \"%s\" while generating update at line %d", 551 strerror(towire.error), towire.line); 552 update_finished(update, dns_rcode_servfail); 553 return; 554 } 555 556 #ifdef DEBUG_DECODE_UPDATE 557 if (!dns_wire_parse(&decoded, msg, update->update_length, false)) { 558 ERROR("Constructed message does not successfully parse."); 559 update_finished(update, dns_rcode_servfail); 560 return; 561 } 562 #endif 563 564 // Transmit the update 565 iov[0].iov_base = update->update; 566 iov[0].iov_len = update->update_length; 567 update->server->send_response(update->server, update->message, iov, 1); 568 } 569 570 void 571 update_connect_callback(comm_t *comm) 572 { 573 update_t *update = comm->context; 574 575 // Once we're connected, construct the first update. 576 INFO("Connected to " PUB_S_SRP ".", comm->name); 577 // STATE CHANGE: connect_to_server -> refresh_existing 578 update->state = refresh_existing; 579 if (!construct_update(update)) { 580 update_finished(update, dns_rcode_servfail); 581 return; 582 } 583 update_send(update); 584 } 585 586 const char *NONNULL 587 update_state_name(update_state_t state) 588 { 589 switch(state) { 590 case connect_to_server: 591 return "connect_to_server"; 592 case create_nonexistent: 593 return "create_nonexistent"; 594 case refresh_existing: 595 return "refresh_existing"; 596 case create_nonexistent_instance: 597 return "create_nonexistent_instance"; 598 case refresh_existing_instance: 599 return "refresh_existing_instance"; 600 case create_nonexistent_host: 601 return "create_nonexistent_host"; 602 case refresh_existing_host: 603 return "refresh_existing_host"; 604 case delete_failed_instance: 605 return "delete_failed_instance"; 606 } 607 return "unknown state"; 608 } 609 610 void 611 update_finalize(io_t *context) 612 { 613 } 614 615 void 616 update_disconnect_callback(comm_t *comm, int error) 617 { 618 update_t *update = comm->context; 619 620 if (update->state == connect_to_server) { 621 INFO(PUB_S_SRP " disconnected: " PUB_S_SRP, comm->name, strerror(error)); 622 update_finished(update, dns_rcode_servfail); 623 } else { 624 // This could be bad if any updates succeeded. 625 ERROR("%s disconnected during update in state %s: %s", 626 comm->name, update_state_name(update->state), strerror(error)); 627 update_finished(update, dns_rcode_servfail); 628 } 629 } 630 631 void 632 update_reply_callback(comm_t *comm) 633 { 634 update_t *update = comm->context; 635 dns_wire_t *wire = &comm->message->wire; 636 char namebuf[DNS_MAX_NAME_SIZE + 1], namebuf1[DNS_MAX_NAME_SIZE + 1]; 637 service_instance_t **pinstance; 638 update_state_t initial_state; 639 service_instance_t *initial_instance; 640 641 initial_instance = update->instance; 642 initial_state = update->state; 643 644 INFO("Message from " PUB_S_SRP " in state " PUB_S_SRP ", rcode = " PUB_S_SRP ".", comm->name, 645 update_state_name(update->state), dns_rcode_name(dns_rcode_get(wire))); 646 647 // Sanity check the response 648 if (dns_qr_get(wire) == dns_qr_query) { 649 ERROR("Received a query from the authoritative server!"); 650 update_finished(update, dns_rcode_servfail); 651 return; 652 } 653 if (dns_opcode_get(wire) != dns_opcode_update) { 654 ERROR("Received a response with opcode %d from the authoritative server!", 655 dns_opcode_get(wire)); 656 update_finished(update, dns_rcode_servfail); 657 return; 658 } 659 if (update->update == NULL) { 660 ERROR("Received a response from auth server when no update has been sent yet."); 661 update_finished(update, dns_rcode_servfail); 662 } 663 // This isn't an error in the protocol, because we might be pipelining. But we _aren't_ pipelining, 664 // so there is only one message in flight. So the message IDs should match. 665 if (update->update->id != wire->id) { 666 ERROR("Response doesn't have the expected id: %x != %x.", wire->id, update->update->id); 667 update_finished(update, dns_rcode_servfail); 668 } 669 670 // Handle the case where the update succeeded. 671 switch(dns_rcode_get(wire)) { 672 case dns_rcode_noerror: 673 switch(update->state) { 674 case connect_to_server: // Can't get a response when connecting. 675 invalid: 676 ERROR("Invalid rcode \"%s\" for state %s", 677 dns_rcode_name(dns_rcode_get(wire)), update_state_name(update->state)); 678 update_finished(update, dns_rcode_servfail); 679 return; 680 681 case create_nonexistent: 682 DM_NAME_GEN_SRP(update->host->name, freshly_added_name_buf); 683 INFO("SRP Update for host " PRI_DM_NAME_SRP " was freshly added.", 684 DM_NAME_PARAM_SRP(update->host->name, freshly_added_name_buf)); 685 update_finished(update, dns_rcode_noerror); 686 return; 687 688 case refresh_existing: 689 DM_NAME_GEN_SRP(update->host->name, refreshed_name_buf); 690 INFO("SRP Update for host " PRI_DM_NAME_SRP " was refreshed.", 691 DM_NAME_PARAM_SRP(update->host->name, refreshed_name_buf)); 692 update_finished(update, dns_rcode_noerror); 693 return; 694 695 case create_nonexistent_instance: 696 DM_NAME_GEN_SRP(update->instance->name, create_instance_buf); 697 INFO("Instance create for " PRI_DM_NAME_SRP " succeeded", 698 DM_NAME_PARAM_SRP(update->instance->name, create_instance_buf)); 699 // If we created a new instance, we need to remember it in case we have to undo it. 700 // To do that, we have to take it off the list. 701 for (pinstance = &update->instances; *pinstance != NULL; pinstance = &((*pinstance)->next)) { 702 if (*pinstance == update->instance) { 703 break; 704 } 705 } 706 *pinstance = update->instance->next; 707 // If there are no more instances to update, then do the host add. 708 if (*pinstance == NULL) { 709 // STATE CHANGE: create_nonexistent_instance -> create_nonexistent_host 710 update->state = create_nonexistent_host; 711 } else { 712 // Not done yet, do the next one. 713 update->instance = *pinstance; 714 } 715 break; 716 717 case refresh_existing_instance: 718 DM_NAME_GEN_SRP(update->instance->name, refreshed_instance_buf); 719 INFO("Instance refresh for " PRI_S_SRP " succeeded", 720 DM_NAME_PARAM_SRP(update->instance->name, refreshed_instance_buf)); 721 722 // Move on to the next instance to update. 723 update->instance = update->instance->next; 724 // If there are no more instances to update, then do the host add. 725 if (update->instance == NULL) { 726 // STATE CHANGE: refresh_existing_instance -> create_nonexistent_host 727 update->state = create_nonexistent_host; 728 } else { 729 // Not done yet, do the next one. 730 // STATE CHANGE: refresh_existing_instance -> create_nonexistent_instance 731 update->state = create_nonexistent_instance; 732 } 733 break; 734 735 case create_nonexistent_host: 736 DM_NAME_GEN_SRP(update->instance->name, new_host_buf); 737 INFO("SRP Update for new host " PRI_S_SRP " was successful.", 738 DM_NAME_PARAM_SRP(update->instance->name, new_host_buf)); 739 update_finished(update, dns_rcode_noerror); 740 return; 741 742 case refresh_existing_host: 743 DM_NAME_GEN_SRP(update->instance->name, existing_host_buf); 744 INFO("SRP Update for existing host " PRI_S_SRP " was successful.", 745 DM_NAME_PARAM_SRP(update->instance->name, existing_host_buf)); 746 update_finished(update, dns_rcode_noerror); 747 return; 748 749 case delete_failed_instance: 750 DM_NAME_GEN_SRP(update->host->name, failed_instance_buf); 751 INFO("Instance deletes for host %s succeeded", 752 DM_NAME_PARAM_SRP(update->host->name, failed_instance_buf)); 753 update_finished(update, update->fail_rcode); 754 return; 755 } 756 break; 757 758 // We will get NXRRSET if we were adding an existing host with the prerequisite that a KEY 759 // RR exist on the name with the specified value. Some other KEY RR may exist, or there may 760 // be no such RRSET; we can't tell from this response. 761 case dns_rcode_nxrrset: 762 switch(update->state) { 763 case connect_to_server: // Can't get a response while connecting. 764 case create_nonexistent: // Can't get nxdomain when creating. 765 case create_nonexistent_instance: // same 766 case create_nonexistent_host: // same 767 case delete_failed_instance: // There are no prerequisites for deleting failed instances, so 768 // in principle this should never fail. 769 goto invalid; 770 771 case refresh_existing: 772 // If we get an NXDOMAIN when doing a refresh, it means either that there is a conflict, 773 // or that one of the instances we are refreshing doesn't exist. So now do the instances 774 // one at a time. 775 776 // STATE CHANGE: refresh_existing -> create_nonexistent 777 update->state = create_nonexistent; 778 update->instance = update->instances; 779 break; 780 781 case refresh_existing_instance: 782 // In this case, we tried to update an existing instance and found that the prerequisite 783 // didn't match. This means either that there is a conflict, or else that the instance 784 // expired and was deleted between the time that we attempted to create it and the time 785 // we attempted to update it. We could account for this with an create_nonexistent_instance_again 786 // state, but currently do not. 787 788 // If we have added some instances, we need to delete them before we send the fail response. 789 if (update->added_instances != NULL) { 790 // STATE CHANGE: refresh_existing_instance -> delete_failed_instance 791 update->state = delete_failed_instance; 792 delete_added_instances: 793 update->instance = update->added_instances; 794 update->fail_rcode = dns_rcode_get(wire); 795 break; 796 } else { 797 update_finished(update, dns_rcode_get(wire)); 798 return; 799 } 800 801 case refresh_existing_host: 802 // In this case, there is a conflicting host entry. This means that all the service 803 // instances that exist and are owned by the key we are using are bogus, whether we 804 // created them or they were already there. However, it is not our mission to remove 805 // pre-existing messes here, so we'll just delete the ones we added. 806 if (update->added_instances != NULL) { 807 // STATE CHANGE: refresh_existing_host -> delete_failed_instance 808 update->state = delete_failed_instance; 809 goto delete_added_instances; 810 } 811 update_finished(update, dns_rcode_get(wire)); 812 return; 813 } 814 break; 815 // We get YXDOMAIN if we specify a prerequisite that the name not exist, but it does exist. 816 case dns_rcode_yxdomain: 817 switch(update->state) { 818 case connect_to_server: // We can't get a response while connecting. 819 case refresh_existing: // If we are refreshing, our prerequisites are all looking for 820 case refresh_existing_instance: // a specific RR with a specific value, so we can never get 821 case refresh_existing_host: // YXDOMAIN. 822 case delete_failed_instance: // And if we are deleting failed instances, we should never get an error. 823 goto invalid; 824 825 case create_nonexistent: 826 // If we get an NXDOMAIN when doing a refresh, it means either that there is a conflict, 827 // or that one of the instances we are refreshing doesn't exist. So now do the instances 828 // one at a time. 829 830 // STATE CHANGE: create_nonexistent -> create_nonexistent_instance 831 update->state = create_nonexistent_instance; 832 update->instance = update->instances; 833 break; 834 835 case create_nonexistent_instance: 836 // STATE CHANGE: create_nonexistent_instance -> refresh_existing_instance 837 update->state = refresh_existing_instance; 838 break; 839 840 case create_nonexistent_host: 841 // STATE CHANGE: create_nonexistent_host -> refresh_existing_host 842 update->state = refresh_existing_host; 843 break; 844 } 845 break; 846 847 case dns_rcode_notauth: 848 ERROR("DNS Authoritative server does not think we are authorized to update it, please fix."); 849 update_finished(update, dns_rcode_servfail); 850 return; 851 852 // We may want to return different error codes or do more informative logging for some of these: 853 case dns_rcode_formerr: 854 case dns_rcode_servfail: 855 case dns_rcode_notimp: 856 case dns_rcode_refused: 857 case dns_rcode_yxrrset: 858 case dns_rcode_notzone: 859 case dns_rcode_dsotypeni: 860 default: 861 goto invalid; 862 } 863 864 if (update->state != initial_state) { 865 INFO("Update state changed from " PUB_S_SRP " to " PUB_S_SRP, update_state_name(initial_state), 866 update_state_name(update->state)); 867 } 868 if (update->instance != initial_instance) { 869 DM_NAME_GEN_SRP(initial_instance->name, initial_name_buf); 870 DM_NAME_GEN_SRP(update->instance->name, updated_name_buf); 871 INFO("Update instance changed from " PRI_DM_NAME_SRP " to " PRI_DM_NAME_SRP, 872 DM_NAME_PARAM_SRP(initial_instance->name, initial_name_buf), 873 DM_NAME_PARAM_SRP(update->instance->name, updated_name_buf)); 874 } 875 if (construct_update(update)) { 876 update_send(update); 877 } else { 878 ERROR("Failed to construct update"); 879 update_finished(update, dns_rcode_servfail); 880 } 881 return; 882 } 883 884 bool 885 srp_update_start(comm_t *connection, dns_message_t *parsed_message, dns_host_description_t *host, 886 service_instance_t *instance, service_t *service, dns_name_t *update_zone, 887 uint32_t lease_time, uint32_t key_lease_time) 888 { 889 update_t *update; 890 891 // Allocate the data structure 892 update = calloc(1, sizeof *update); 893 if (update == NULL) { 894 ERROR("start_dns_update: unable to allocate update structure!"); 895 return false; 896 } 897 // Allocate the buffer in which updates will be constructed. 898 update->update = calloc(1, DNS_MAX_UDP_PAYLOAD); 899 if (update->update == NULL) { 900 ERROR("start_dns_update: unable to allocate update message buffer."); 901 return false; 902 } 903 update->update_max = DNS_DATA_SIZE; 904 905 // Retain the stuff we're supposed to send. 906 update->host = host; 907 update->instances = instance; 908 update->services = service; 909 update->parsed_message = parsed_message; 910 update->message = connection->message; 911 update->state = connect_to_server; 912 update->zone_name = update_zone; 913 update->client = connection; 914 915 // Start the connection to the server 916 update->server = ioloop_connect(&dns_server, false, true, update_reply_callback, 917 update_connect_callback, update_disconnect_callback, update_finalize, update); 918 if (update->server == NULL) { 919 free(update); 920 return false; 921 } 922 INFO("Connecting to auth server."); 923 return true; 924 } 925 926 static bool 927 key_handler(void *context, const char *filename, char **hunks, int num_hunks, int lineno) 928 { 929 hmac_key_t *key = context; 930 long val; 931 char *endptr; 932 size_t len; 933 uint8_t keybuf[SRP_SHA256_DIGEST_SIZE]; 934 int error; 935 936 // Validate the constant-size stuff first. 937 if (strcasecmp(hunks[1], "in")) { 938 ERROR("Expecting tsig key class IN, got %s.", hunks[1]); 939 return false; 940 } 941 942 if (strcasecmp(hunks[2], "key")) { 943 ERROR("expecting tsig key type KEY, got %s", hunks[2]); 944 return false; 945 } 946 947 // There's not much meaning to be extracted from the flags. 948 val = strtol(hunks[3], &endptr, 10); 949 if (*endptr != 0 || endptr == hunks[3]) { 950 ERROR("Invalid key flags: %s", hunks[3]); 951 return false; 952 } 953 954 // The protocol number as produced by BIND will always be 3, meaning DNSSEC, but of 955 // course we aren't using this key for DNSSEC, so it's not clear that we should take 956 // this seriously; hence we just check to see that it's a number. 957 val = strtol(hunks[4], &endptr, 10); 958 if (*endptr != 0 || endptr == hunks[4]) { 959 ERROR("Invalid protocol number: %s", hunks[4]); 960 return false; 961 } 962 963 // The key algorithm should be HMAC-SHA253. BIND uses 163, but this is not registered 964 // with IANA. So again, we don't actually require this, but we do validate it so that 965 // if someone generated the wrong key type, they'll get a message. 966 val = strtol(hunks[5], &endptr, 10); 967 if (*endptr != 0 || endptr == hunks[5]) { 968 ERROR("Invalid protocol number: %s", hunks[5]); 969 return false; 970 } 971 if (val != 163) { 972 INFO("Warning: Protocol number for HMAC-SHA256 TSIG KEY is not 163, but %ld", val); 973 } 974 975 key->name = dns_pres_name_parse(hunks[0]); 976 if (key->name == NULL) { 977 ERROR("Invalid key name: %s", hunks[0]); 978 return false; 979 } 980 981 error = srp_base64_parse(hunks[6], &len, keybuf, sizeof keybuf); 982 if (error != 0) { 983 ERROR("Invalid HMAC-SHA256 key: %s", strerror(errno)); 984 goto fail; 985 } 986 987 // The key should be 32 bytes (256 bits). 988 if (len == 0) { 989 ERROR("Invalid (null) secret for key %s", hunks[0]); 990 goto fail; 991 } 992 key->secret = malloc(len); 993 if (key->secret == NULL) { 994 ERROR("Unable to allocate space for secret for key %s", hunks[0]); 995 fail: 996 dns_name_free(key->name); 997 key->name = NULL; 998 return false; 999 } 1000 memcpy(key->secret, keybuf, len); 1001 key->length = len; 1002 key->algorithm = SRP_HMAC_TYPE_SHA256; 1003 return true; 1004 } 1005 1006 config_file_verb_t key_verbs[] = { 1007 { NULL, 7, 7, key_handler } 1008 }; 1009 #define NUMKEYVERBS ((sizeof key_verbs) / sizeof (config_file_verb_t)) 1010 1011 hmac_key_t * 1012 parse_hmac_key_file(const char *filename) 1013 { 1014 hmac_key_t *key = calloc(1, sizeof *key); 1015 if (key == NULL) { 1016 ERROR("No memory for tsig key structure."); 1017 return NULL; 1018 } 1019 if (!config_parse(key, filename, key_verbs, NUMKEYVERBS)) { 1020 ERROR("Failed to parse key file."); 1021 free(key); 1022 return NULL; 1023 } 1024 return key; 1025 } 1026 1027 int 1028 main(int argc, char **argv) 1029 { 1030 int i; 1031 subnet_t *tcp_validators = NULL; 1032 udp_validator_t *udp_validators = NULL; 1033 udp_validator_t *NULLABLE *NONNULL up = &udp_validators; 1034 subnet_t *NULLABLE *NONNULL nt = &tcp_validators; 1035 subnet_t *NULLABLE *NONNULL sp; 1036 addr_t pref; 1037 uint16_t port; 1038 socklen_t len, prefalen; 1039 char *s, *p; 1040 int width; 1041 bool got_server = false; 1042 1043 // Read the configuration from the command line. 1044 for (i = 1; i < argc; i++) { 1045 if (!strcmp(argv[i], "-s")) { 1046 if (got_server) { 1047 ERROR("only one authoritative server can be specified."); 1048 return usage(argv[0]); 1049 } 1050 if (++i == argc) { 1051 ERROR("-s is missing dns server IP address."); 1052 return usage(argv[0]); 1053 } 1054 len = getipaddr(&dns_server, argv[i]); 1055 if (!len) { 1056 ERROR("Invalid IP address: %s.", argv[i]); 1057 return usage(argv[0]); 1058 } 1059 if (++i == argc) { 1060 ERROR("-s is missing dns server port."); 1061 return usage(argv[0]); 1062 } 1063 port = strtol(argv[i], &s, 10); 1064 if (s == argv[i] || s[0] != '\0') { 1065 ERROR("Invalid port number: %s", argv[i]); 1066 return usage(argv[0]); 1067 } 1068 if (dns_server.sa.sa_family == AF_INET) { 1069 dns_server.sin.sin_port = htons(port); 1070 } else { 1071 dns_server.sin6.sin6_port = htons(port); 1072 } 1073 got_server = true; 1074 } else if (!strcmp(argv[i], "-k")) { 1075 if (++i == argc) { 1076 ERROR("-k is missing key file name."); 1077 return usage(argv[0]); 1078 } 1079 key = parse_hmac_key_file(argv[i]); 1080 // Someething should already have printed the error message. 1081 if (key == NULL) { 1082 return 1; 1083 } 1084 } else if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "-u")) { 1085 if (!strcmp(argv[i], "-u")) { 1086 if (++i == argc) { 1087 ERROR("-u is missing interface name."); 1088 return usage(argv[0]); 1089 } 1090 *up = calloc(1, sizeof **up); 1091 if (*up == NULL) { 1092 ERROR("udp_validators: out of memory."); 1093 return usage(argv[0]); 1094 } 1095 (*up)->ifname = strdup(argv[i]); 1096 if ((*up)->ifname == NULL) { 1097 ERROR("udp validators: ifname: out of memory."); 1098 return usage(argv[0]); 1099 } 1100 sp = &((*up)->subnets); 1101 } else { 1102 sp = nt; 1103 } 1104 1105 if (++i == argc) { 1106 ERROR("%s requires at least one prefix.", argv[i - 1]); 1107 return usage(argv[0]); 1108 } 1109 s = strchr(argv[i], '/'); 1110 if (s == NULL) { 1111 ERROR("%s is not a prefix.", argv[i]); 1112 return usage(argv[0]); 1113 } 1114 *s = 0; 1115 ++s; 1116 prefalen = getipaddr(&pref, argv[i]); 1117 if (!prefalen) { 1118 ERROR("%s is not a valid prefix address.", argv[i]); 1119 return usage(argv[0]); 1120 } 1121 width = strtol(s, &p, 10); 1122 if (s == p || p[0] != '\0') { 1123 ERROR("%s (prefix width) is not a number.", p); 1124 return usage(argv[0]); 1125 } 1126 if (width < 0 || 1127 (pref.sa.sa_family == AF_INET && width > 32) || 1128 (pref.sa.sa_family == AF_INET6 && width > 64)) { 1129 ERROR("%s is not a valid prefix length for %s", p, 1130 pref.sa.sa_family == AF_INET ? "IPv4" : "IPv6"); 1131 return usage(argv[0]); 1132 } 1133 1134 *nt = calloc(1, sizeof **nt); 1135 if (!*nt) { 1136 ERROR("tcp_validators: out of memory."); 1137 return 1; 1138 } 1139 1140 (*nt)->preflen = width; 1141 (*nt)->family = pref.sa.sa_family; 1142 if (pref.sa.sa_family == AF_INET) { 1143 memcpy((*nt)->bytes, &pref.sin.sin_addr, 4); 1144 } else { 1145 memcpy((*nt)->bytes, &pref.sin6.sin6_addr, 8); 1146 } 1147 1148 // *up will be non-null for -u and null for -t. 1149 if (*up) { 1150 up = &((*up)->next); 1151 } else { 1152 nt = sp; 1153 } 1154 } 1155 } 1156 if (!got_server) { 1157 ERROR("No authoritative DNS server specified to take updates!"); 1158 return 1; 1159 } 1160 1161 if (!ioloop_init()) { 1162 return 1; 1163 } 1164 1165 if (!srp_proxy_listen("home.arpa")) { 1166 return 1; 1167 } 1168 1169 // For now, hardcoded, should be configurable 1170 service_update_zone = dns_pres_name_parse("home.arpa"); 1171 1172 do { 1173 int something = 0; 1174 something = ioloop_events(0); 1175 INFO("dispatched %d events.", something); 1176 } while (1); 1177 } 1178 1179 // Local Variables: 1180 // mode: C 1181 // tab-width: 4 1182 // c-file-style: "bsd" 1183 // c-basic-offset: 4 1184 // fill-column: 108 1185 // indent-tabs-mode: nil 1186 // End: 1187