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