1 /* Find public key in DNS
2 * Copyright (C) 2000-2002 D. Hugh Redelmeier.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * RCSID $Id: dnskey.c,v 1.36 2002/03/23 03:33:19 dhr Exp $
22 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/nameser.h>
28 #include <netdb.h> /* ??? for h_errno */
32 #include "adns.h" /* needs <resolv.h> */
33 #include "constants.h"
38 #include "connections.h" /* needs id.h */
39 #include "preshared.h" /* needs connections.h */
47 int adns_qfd = NULL_FD, /* file descriptor for sending queries to adns */
48 adns_afd = NULL_FD; /* file descriptor for receiving answers from adns */
49 static pid_t adns_pid = 0;
50 const char *pluto_adns_option = NULL; /* path from --pluto_adns */
56 const char *adns_path = pluto_adns_option;
57 static const char adns_name[] = "_pluto_adns";
58 char adns_path_space[4096]; /* plenty long? */
64 /* find a pathname to the ADNS program */
65 if (adns_path == NULL)
67 /* pathname was not specified as an option: build it.
68 * First, figure out the directory to be used.
70 const char *ipsec_dir = getenv("IPSEC_DIR");
73 if (ipsec_dir != NULL)
75 /* IPSEC_DIR specifies the directory */
76 n = strlen(ipsec_dir);
77 if ((size_t)n <= sizeof(adns_path_space) - sizeof(adns_name))
79 strcpy(adns_path_space, ipsec_dir);
80 if (n > 0 && adns_path_space[n -1] != '/')
81 adns_path_space[n++] = '/';
86 /* The program will be in the same directory as Pluto,
87 * so we use the sympolic link /proc/self/exe to
88 * tell us of the path prefix.
90 n = readlink("/proc/self/exe", adns_path_space, sizeof(adns_path_space));
94 , "readlink(\"/proc/self/exe\") failed in init_adns()"));
98 if ((size_t)n > sizeof(adns_path_space) - sizeof(adns_name))
99 exit_log("path to %s is too long", adns_name);
101 while (n > 0 && adns_path_space[n - 1] != '/')
104 strcpy(adns_path_space + n, adns_name);
105 adns_path = adns_path_space;
107 if (access(adns_path, X_OK) < 0)
108 exit_log_errno((e, "%s missing or not executable", adns_path));
111 if (pipe(qfds) != 0 || pipe(afds) != 0)
112 exit_log_errno((e, "pipe(2) failed in init_adns()"));
114 snprintf(qfd_str, sizeof(qfd_str), "%d", qfds[0]);
115 snprintf(afd_str, sizeof(afd_str), "%d", afds[1]);
125 exit_log_errno((e, "fork() failed in init_adns()"));
135 /* this isn't elegantly covered by our macros */
136 if (cur_debugging & DBG_DNS)
137 execlp(adns_path, adns_name, "-d", qfd_str, afd_str, NULL);
139 execlp(adns_path, adns_name, qfd_str, afd_str, NULL);
141 execlp(adns_path, adns_name, qfd_str, afd_str, NULL);
146 exit_log_errno((e, "execlp of %s failed", adns_path));
169 pid_t p = waitpid(adns_pid, &status, 0);
173 log_errno((e, "waitpid for ADNS process failed"));
175 else if (WIFEXITED(status))
177 if (WEXITSTATUS(status) != 0)
178 log("ADNS process exited with status %d"
179 , (int) WEXITSTATUS(status));
181 else if (WIFSIGNALED(status))
183 log("ADNS process terminated by signal %d", (int)WTERMSIG(status));
187 log("wait for end of ADNS process returned odd status 0x%x\n"
195 /* tricky macro to pass any hot potato */
196 #define TRY(x) { err_t ugh = x; if (ugh != NULL) return ugh; }
199 /* structure of Query Reply (RFC 1035 4.1.1):
201 * +---------------------+
203 * +---------------------+
204 * | Question | the question for the name server
205 * +---------------------+
206 * | Answer | RRs answering the question
207 * +---------------------+
208 * | Authority | RRs pointing toward an authority
209 * +---------------------+
210 * | Additional | RRs holding additional information
211 * +---------------------+
214 /* Header section format (as modified by RFC 2535 6.1):
216 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
217 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
219 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
220 * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE |
221 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
223 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
225 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
227 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
229 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
232 u_int16_t id; /* 16-bit identifier to match query */
234 u_int16_t stuff; /* packed crud: */
236 #define QRS_QR 0x8000 /* QR: on if this is a response */
238 #define QRS_OPCODE_SHIFT 11 /* OPCODE field */
239 #define QRS_OPCODE_MASK 0xF
240 #define QRSO_QUERY 0 /* standard query */
241 #define QRSO_IQUERY 1 /* inverse query */
242 #define QRSO_STATUS 2 /* server status request query */
244 #define QRS_AA 0x0400 /* AA: on if Authoritative Answer */
245 #define QRS_TC 0x0200 /* TC: on if truncation happened */
246 #define QRS_RD 0x0100 /* RD: on if recursion desired */
247 #define QRS_RA 0x0080 /* RA: on if recursion available */
248 #define QRS_Z 0x0040 /* Z: reserved; must be zero */
249 #define QRS_AD 0x0020 /* AD: on if authentic data (RFC 2535) */
250 #define QRS_CD 0x0010 /* AD: on if checking disabled (RFC 2535) */
252 #define QRS_RCODE_SHIFT 0 /* RCODE field: response code */
253 #define QRS_RCODE_MASK 0xF
257 u_int16_t qdcount; /* number of entries in question section */
258 u_int16_t ancount; /* number of resource records in answer section */
259 u_int16_t nscount; /* number of name server resource records in authority section */
260 u_int16_t arcount; /* number of resource records in additional records section */
263 static field_desc qr_header_fields[] = {
264 { ft_nat, 16/BITS_PER_BYTE, "ID", NULL },
265 { ft_nat, 16/BITS_PER_BYTE, "stuff", NULL },
266 { ft_nat, 16/BITS_PER_BYTE, "QD Count", NULL },
267 { ft_nat, 16/BITS_PER_BYTE, "Answer Count", NULL },
268 { ft_nat, 16/BITS_PER_BYTE, "Authority Count", NULL },
269 { ft_nat, 16/BITS_PER_BYTE, "Additional Count", NULL },
270 { ft_end, 0, NULL, NULL }
273 static struct_desc qr_header_desc = {
274 "Query Response Header",
276 sizeof(struct qr_header)
279 /* Messages for codes in RCODE (see RFC 1035 4.1.1) */
280 static const err_t rcode_text[QRS_RCODE_MASK + 1] = {
281 NULL, /* not an error */
282 "Format error - The name server was unable to interpret the query",
283 "Server failure - The name server was unable to process this query"
284 " due to a problem with the name server",
285 "Name Error - Meaningful only for responses from an authoritative name"
286 " server, this code signifies that the domain name referenced in"
287 " the query does not exist",
288 "Not Implemented - The name server does not support the requested"
290 "Refused - The name server refuses to perform the specified operation"
291 " for policy reasons",
292 /* the rest are reserved for future use */
296 rr_typename(int type)
309 /* throw away a possibly compressed domain name */
312 eat_name(pb_stream *pbs)
314 u_char name_buf[NS_MAXDNAME + 2];
315 u_char *ip = pbs->cur;
317 unsigned jump_count = 0;
324 return "ran out of message while skipping domain name";
336 /* we grab the next b characters */
337 if (oi + b > NS_MAXDNAME)
338 return "domain name too long";
340 if (pbs->roof - ip <= b)
341 return "domain name falls off end of message";
344 name_buf[oi++] = '.';
346 memcpy(name_buf + oi, ip, b);
358 return "ran out of message in middle of compressed domain name";
360 ix = ((b & ~0xC0u) << 8) | *ip++;
364 if (ix >= pbs_room(pbs))
365 return "impossible compressed domain name";
367 /* Avoid infinite loop.
368 * There can be no more jumps than there are bytes
369 * in the packet. Not a tight limit, but good enough.
372 if (jump_count > pbs_room(pbs))
373 return "loop in compressed domain name";
375 ip = pbs->start + ix;
380 return "invalid code in label";
384 name_buf[oi++] = '\0';
386 DBG(DBG_DNS, DBG_log("skipping name %s", name_buf));
392 eat_name_helpfully(pb_stream *pbs, const char *context)
394 err_t ugh = eat_name(pbs);
396 return ugh == NULL? ugh
397 : builddiag("malformed name within DNS record of %s: %s", context, ugh);
400 /* non-variable part of 4.1.2 Question Section entry:
402 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
403 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
407 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
409 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
411 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
419 static field_desc qs_fixed_fields[] = {
420 { ft_loose_enum, 16/BITS_PER_BYTE, "QTYPE", &rr_qtype_names },
421 { ft_loose_enum, 16/BITS_PER_BYTE, "QCLASS", &rr_class_names },
422 { ft_end, 0, NULL, NULL }
425 static struct_desc qs_fixed_desc = {
426 "Question Section entry fixed part",
428 sizeof(struct qs_fixed)
431 /* 4.1.3. Resource record format:
433 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
434 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
439 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
441 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
443 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
446 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
448 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
451 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
457 u_int32_t ttl; /* actually signed */
462 static field_desc rr_fixed_fields[] = {
463 { ft_loose_enum, 16/BITS_PER_BYTE, "type", &rr_type_names },
464 { ft_loose_enum, 16/BITS_PER_BYTE, "class", &rr_class_names },
465 { ft_nat, 32/BITS_PER_BYTE, "TTL", NULL },
466 { ft_nat, 16/BITS_PER_BYTE, "RD length", NULL },
467 { ft_end, 0, NULL, NULL }
470 static struct_desc rr_fixed_desc = {
471 "Resource Record fixed part",
473 /* note: following is tricky: avoids padding problems */
474 offsetof(struct rr_fixed, rdlength) + sizeof(u_int16_t)
477 /* RFC 1035 3.3.14: TXT RRs have text in the RDATA field.
478 * It is in the form of a sequence of <character-string>s as described in 3.3.
479 * unpack_txt_rdata() deals with this peculiar representation.
482 /* RFC 2535 3.1 KEY RDATA format:
484 * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
485 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
486 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
487 * | flags | protocol | algorithm |
488 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
492 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
501 static field_desc key_rdata_fields[] = {
502 { ft_nat, 16/BITS_PER_BYTE, "flags", NULL },
503 { ft_nat, 8/BITS_PER_BYTE, "protocol", NULL },
504 { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL },
505 { ft_end, 0, NULL, NULL }
508 static struct_desc key_rdata_desc = {
509 "KEY RR RData fixed part",
511 sizeof(struct key_rdata)
514 /* RFC 2535 4.1 SIG RDATA format:
516 * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
517 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
518 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
519 * | type covered | algorithm | labels |
520 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
522 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
523 * | signature expiration |
524 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
525 * | signature inception |
526 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
528 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ signer's name +
530 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-/
534 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
538 u_int16_t type_covered;
541 u_int32_t original_ttl;
542 u_int32_t sig_expiration;
543 u_int32_t sig_inception;
547 static field_desc sig_rdata_fields[] = {
548 { ft_nat, 16/BITS_PER_BYTE, "type_covered", NULL},
549 { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL},
550 { ft_nat, 8/BITS_PER_BYTE, "labels", NULL},
551 { ft_nat, 32/BITS_PER_BYTE, "original ttl", NULL},
552 { ft_nat, 32/BITS_PER_BYTE, "sig expiration", NULL},
553 { ft_nat, 32/BITS_PER_BYTE, "sig inception", NULL},
554 { ft_nat, 16/BITS_PER_BYTE, "key tag", NULL},
555 { ft_end, 0, NULL, NULL }
558 static struct_desc sig_rdata_desc = {
559 "SIG RR RData fixed part",
561 sizeof(struct sig_rdata)
564 /****************************************************************/
567 build_dns_name(u_char name_buf[NS_MAXDNAME + 2]
568 , const struct id *id
569 , const char *typename USED_BY_DEBUG)
571 /* note: all end in "." to suppress relative searches */
576 /* XXX: this is really ugly and only temporary until addrtot can
577 * generate the correct format
579 const unsigned char *b;
580 size_t bl USED_BY_DEBUG = addrbytesptr(&id->ip_addr, &b);
583 snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa."
584 , b[3], b[2], b[1], b[0]);
590 /* ??? is this correct? */
591 const unsigned char *b;
593 u_char *op = name_buf;
594 static const char suffix[] = "IP6.INT.";
596 for (bl = addrbytesptr(&id->ip_addr, &b); bl-- != 0; )
598 if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
599 return "IPv6 reverse name too long";
600 op += sprintf(op, "%x.%x.", b[bl] & 0xF, b[bl] >> 4);
607 if (id->name.len > NS_MAXDNAME)
608 return "FQDN too long for domain name";
610 memcpy(name_buf, id->name.ptr, id->name.len);
611 strcpy(name_buf + id->name.len, ".");
615 return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR";
618 DBG(DBG_CONTROL | DBG_DNS, DBG_log("Querying DNS for %s for %s"
619 , typename, name_buf));
623 /* handle a key Resource Record. */
625 struct pubkeyrec *keys_from_dns = NULL; /* ephemeral! extracted keys */
628 process_key_rr(u_char *ptr, size_t len
629 , bool doit /* should we capture information? */
630 , enum dns_auth_level dns_auth_level
631 , int *goodies /* where we count accepted RRs */
632 , const struct id *id) /* subject of query (i.e. client) */
637 if (len < sizeof(struct key_rdata))
638 return "KEY Resource Record's RD Length is too small";
640 init_pbs(&pbs, ptr, len, "KEY RR");
642 if (!in_struct(&kr, &key_rdata_desc, &pbs, NULL))
643 return "failed to get fixed part of KEY Resource Record RDATA";
645 if (kr.protocol == 4 /* IPSEC (RFC 2535 3.1.3) */
646 && kr.algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */
647 && (kr.flags & 0x8000) == 0 /* use for authentication (3.1.2) */
648 && (kr.flags & 0x2CF0) == 0) /* must be zero */
650 /* we have what seems to be a tasty key */
657 setchunk(k, pbs.cur, pbs_left(&pbs));
658 TRY(add_public_key(id, dns_auth_level, PUBKEY_ALG_RSA, &k
666 /* Process TXT X-IPsec-Server record, accumulating relevant ones
667 * in gateways_from_dns, a list sorted by "preference".
669 * Format of TXT record body: X-IPsec-Server ( nnn ) = iii kkk
670 * nnn is a 16-bit unsigned integer preference
671 * iii is @FQDN or dotted-decimal IPv4 address or colon-hex IPv6 address
672 * kkk is an optional RSA public signing key in base 64.
674 * NOTE: we've got to be very wary of anything we find -- bad guys
675 * might have prepared it.
678 #define our_TXT_attr_string "X-IPsec-Server"
679 static const char our_TXT_attr[] = our_TXT_attr_string;
681 struct gw_info *gateways_from_dns = NULL; /* ephemeral! */
683 /* unpack TXT rr RDATA into C string.
684 * A sequence of <character-string>s as described in RFC 1035 3.3.
685 * We concatenate them. If a count is less than 255, we add a space
686 * because that looks more like the "source" version of the record.
689 unpack_txt_rdata(u_char *d, size_t dlen, const u_char *s, size_t slen)
697 int add_sp = cl < 255 && i + cl != slen; /* reconstitute whitespace? */
700 return "TXT rr RDATA representation malformed";
702 if (o + cl + add_sp >= dlen)
703 return "TXT rr RDATA too large";
705 memcpy(d + o, s + i, cl);
713 return "TXT rr RDATA contains a NUL";
719 decode_iii(u_char **pp, struct id *gw_id)
721 u_char *p = *pp + strspn(*pp, " \t");
722 u_char *e = p + strcspn(p, " \t");
726 return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
731 /* gateway specification in this record is @FQDN */
732 err_t ugh = atoid(p, gw_id);
735 return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s"
740 /* gateway specification is numeric */
742 err_t ugh = tnatoaddr(p, e-p
743 , strchr(p, ':') == NULL? AF_INET : AF_INET6
747 return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s"
751 return "gateway address must not be 0.0.0.0 or 0::0";
757 *pp = e + strspn(e, " \t");
763 process_txt_rr(u_char *rdata, size_t rdlen
764 , bool doit /* should we capture information? */
765 , enum dns_auth_level dns_auth_level
766 , int *goodies /* where we count accepted RRs */
767 , const struct id *client_id /* subject of query */
768 , const struct id *peer_id) /* security gateway of interest, if any */
770 u_char str[2049]; /* space for unpacked RDATA */
772 unsigned long pref = 0;
775 TRY(unpack_txt_rdata(str, sizeof(str), rdata, rdlen));
777 p += strspn(p, " \t"); /* ignore leading whitespace */
779 /* is this for us? */
780 if (strncasecmp(p, our_TXT_attr, sizeof(our_TXT_attr)-1) != 0)
781 return NULL; /* neither interesting nor bad */
783 p += sizeof(our_TXT_attr) - 1; /* ignore our attribute name */
784 p += strspn(p, " \t"); /* ignore leading whitespace */
786 /* decode '(' nnn ')' */
788 return "X-IPsec-Server missing '('";
794 pref = strtoul(p, &e, 0);
795 if ((u_char *)e == p)
796 return "malformed X-IPsec-Server priority";
798 p = e + strspn(e, " \t");
801 return "X-IPsec-Server priority missing ')'";
804 p += strspn(p, " \t");
807 return "X-IPsec-Server priority larger than 0xFFFF";
813 return "X-IPsec-Server priority missing '='";
816 p += strspn(p, " \t");
818 /* Decode iii (Security Gateway ID). */
820 zero(&gi); /* before first use */
822 TRY(decode_iii(&p, &gi.gw_id));
826 /* we don't know the peer's ID (because we are initiating
827 * and we don't know who to initiate with.
828 * So we're looking for gateway specs with an IP address
830 if (!id_is_ipaddr(&gi.gw_id))
834 char cidb[IDTOA_BUF];
835 char gwidb[IDTOA_BUF];
837 idtoa(client_id, cidb, sizeof(cidb));
838 idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
839 DBG_log("TXT %s record for %s: security gateway %s;"
840 " ignored because gateway's IP is unspecified"
841 , our_TXT_attr, cidb, gwidb);
843 return NULL; /* we cannot use this record, but it isn't wrong */
848 /* We do know the peer's ID (because we are responding)
849 * So we're looking for gateway specs specifying this known ID.
851 if (!same_id(peer_id, &gi.gw_id))
855 char cidb[IDTOA_BUF];
856 char gwidb[IDTOA_BUF];
857 char pidb[IDTOA_BUF];
859 idtoa(client_id, cidb, sizeof(cidb));
860 idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
861 idtoa(peer_id, pidb, sizeof(pidb));
862 DBG_log("TXT %s record for %s: security gateway %s;"
863 " ignored -- looking to confirm %s as gateway"
864 , our_TXT_attr, cidb, gwidb, pidb);
866 return NULL; /* we cannot use this record, but it isn't wrong */
874 /* really accept gateway */
875 u_char kb[sizeof(str)]; /* plenty of space for binary form of public key */
877 struct gw_info **gwip; /* gateway insertion point */
879 gi.client_id = *client_id; /* will need to unshare_id_content */
881 /* decode optional key */
883 gi.gw_key_present = *p != '\0';
884 if (gi.gw_key_present)
886 /* kkk is base 64 encoding of key */
887 err_t ugh = ttodatav(p, 0, 64, kb, sizeof(kb), &kbc.len
888 , diag_space, sizeof(diag_space));
891 return builddiag("malformed key data: %s", ugh);
893 passert(kbc.len < sizeof(kb));
896 ugh = unpack_RSA_public_key(&gi.gw_key, &kbc);
898 return builddiag("invalid key data: %s", ugh);
901 /* we're home free! Allocate everything and add to gateways list. */
904 gi.dns_auth_level = dns_auth_level;
905 gi.created_time = now();
906 gi.last_tried_time = gi.last_worked_time = NO_TIME;
908 /* find insertion point */
909 for (gwip = &gateways_from_dns; *gwip != NULL && (*gwip)->pref < pref; gwip = &(*gwip)->next)
914 char cidb[IDTOA_BUF];
915 char gwidb[IDTOA_BUF];
917 idtoa(client_id, cidb, sizeof(cidb));
918 idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
919 /* should print key, but it is too long */
920 DBG_log("gateway for %s is %s"
925 *gwip = clone_thing(gi, "gateway info");
926 unshare_id_content(&gateways_from_dns->client_id);
933 gw_addref(struct gw_info *gw)
940 gw_delref(struct gw_info **gwp)
942 struct gw_info *gw = *gwp;
946 passert(gw->refcnt != 0);
950 free_id_content(&gw->client_id);
951 free_id_content(&gw->gw_id);
952 if (gw->gw_key_present)
953 free_RSA_public_content(&gw->gw_key);
954 gw_delref(&gw->next);
955 pfree(gw); /* trickery could make this a tail-call */
962 process_answer_section(pb_stream *pbs
963 , bool doit /* should we capture information? */
964 , enum dns_auth_level *dns_auth_level
965 , u_int16_t ancount /* number of RRs in the answer section */
966 , int type /* type of RR of interest */
967 , const struct id *id /* subject of query (i.e. client) */
968 , const struct id *sgw_id) /* peer's ID */
973 DBG(DBG_DNS, DBG_log("*Answer Section:"));
975 for (c = 0; c != ancount; c++)
980 /* ??? do we need to match the name? */
982 TRY(eat_name_helpfully(pbs, "Answer Section"));
984 if (!in_struct(&rrf, &rr_fixed_desc, pbs, NULL))
985 return "failed to get fixed part of Answer Section Resource Record";
987 if (rrf.rdlength > pbs_left(pbs))
988 return "RD Length extends beyond end of message";
990 /* ??? should we care about ttl? */
994 if (rrf.type == type && rrf.class == C_IN)
1001 ugh = process_key_rr(pbs->cur, tail, doit, *dns_auth_level
1005 ugh = process_txt_rr(pbs->cur, tail, doit, *dns_auth_level
1006 , &goodies, id, sgw_id);
1009 /* Check if SIG RR authenticates what we are learning.
1010 * The RRset covered by a SIG must have the same owner,
1012 * For us, the class is always C_IN, so that matches.
1013 * We decode the SIG RR's fixed part to check
1014 * that the type_covered field matches our query type
1015 * (this may be redundant).
1016 * We don't check the owner (apparently this is the
1017 * name on the record) -- we assume that it matches
1018 * or we would not have been given this SIG in the
1021 * We only look on first pass, and only if we've something
1022 * to learn. This cuts down on useless decoding.
1024 if (!doit && *dns_auth_level == DAL_UNSIGNED)
1026 struct sig_rdata sr;
1028 if (!in_struct(&sr, &sig_rdata_desc, pbs, NULL))
1029 ugh = "failed to get fixed part of SIG Resource Record RDATA";
1030 else if (sr.type_covered == type)
1031 *dns_auth_level = DAL_SIGNED;
1035 ugh = builddiag("unexpected RR type %d", type);
1041 in_raw(NULL, tail, pbs, "RR RDATA");
1044 return goodies > 0? NULL
1045 : builddiag("no suitable %s record found in DNS", rr_typename(type));
1048 /* process DNS answer -- TXT or KEY query */
1051 process_dns_answer(const struct id *id /* subject of query */
1052 , const struct id *sgw_id /* security gw, if fixed */
1053 , u_char ans[], int anslen
1054 , int type) /* type of record being sought */
1056 int r; /* all-purpose return value holder */
1057 u_int16_t c; /* number of current RR in current answer section */
1059 u_int8_t *ans_start; /* saved position of answer section */
1060 struct qr_header qr_header;
1061 enum dns_auth_level dns_auth_level;
1063 init_pbs(&pbs, ans, anslen, "Query Response Message");
1065 /* decode and check header */
1067 if (!in_struct(&qr_header, &qr_header_desc, &pbs, NULL))
1068 return "malformed header";
1070 /* ID: nothing to do with us */
1072 /* stuff -- lots of things */
1073 if ((qr_header.stuff & QRS_QR) == 0)
1074 return "not a response?!?";
1076 if (((qr_header.stuff >> QRS_OPCODE_SHIFT) & QRS_OPCODE_MASK) != QRSO_QUERY)
1077 return "unexpected opcode";
1079 /* I don't think we care about AA */
1081 if (qr_header.stuff & QRS_TC)
1082 return "response truncated";
1084 /* I don't think we care about RD, RA, or CD */
1086 /* AD means "authentic data" */
1087 dns_auth_level = qr_header.stuff & QRS_AD? DAL_UNSIGNED : DAL_NOTSEC;
1089 if (qr_header.stuff & QRS_Z)
1090 return "Z bit is not zero";
1092 r = (qr_header.stuff >> QRS_RCODE_SHIFT) & QRS_RCODE_MASK;
1094 return r < (int)elemsof(rcode_text)? rcode_text[r] : "unknown rcode";
1096 if (qr_header.ancount == 0)
1097 return builddiag("no %s RR found by DNS", rr_typename(type));
1099 /* end of header checking */
1101 /* Question Section processing */
1103 /* 4.1.2. Question section format:
1105 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1106 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1110 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1112 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1114 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1117 DBG(DBG_DNS, DBG_log("*Question Section:"));
1119 for (c = 0; c != qr_header.qdcount; c++)
1121 struct qs_fixed qsf;
1123 TRY(eat_name_helpfully(&pbs, "Question Section"));
1125 if (!in_struct(&qsf, &qs_fixed_desc, &pbs, NULL))
1126 return "failed to get fixed part of Question Section";
1128 if (qsf.qtype != type)
1129 return "unexpected QTYPE in Question Section";
1131 if (qsf.qclass != C_IN)
1132 return "unexpected QCLASS in Question Section";
1135 /* rest of sections are made up of Resource Records */
1137 /* Answer Section processing -- error checking, noting T_SIG */
1139 ans_start = pbs.cur; /* remember start of answer section */
1141 TRY(process_answer_section(&pbs, FALSE, &dns_auth_level
1142 ,qr_header.ancount, type, id, sgw_id));
1144 /* Authority Section processing (just sanity checking) */
1146 DBG(DBG_DNS, DBG_log("*Authority Section:"));
1148 for (c = 0; c != qr_header.nscount; c++)
1150 struct rr_fixed rrf;
1153 TRY(eat_name_helpfully(&pbs, "Authority Section"));
1155 if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
1156 return "failed to get fixed part of Authority Section Resource Record";
1158 if (rrf.rdlength > pbs_left(&pbs))
1159 return "RD Length extends beyond end of message";
1161 /* ??? should we care about ttl? */
1163 tail = rrf.rdlength;
1165 in_raw(NULL, tail, &pbs, "RR RDATA");
1168 /* Additional Section processing (just sanity checking) */
1170 DBG(DBG_DNS, DBG_log("*Additional Section:"));
1172 for (c = 0; c != qr_header.arcount; c++)
1174 struct rr_fixed rrf;
1177 TRY(eat_name_helpfully(&pbs, "Additional Section"));
1179 if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
1180 return "failed to get fixed part of Additional Section Resource Record";
1182 if (rrf.rdlength > pbs_left(&pbs))
1183 return "RD Length extends beyond end of message";
1185 /* ??? should we care about ttl? */
1187 tail = rrf.rdlength;
1189 in_raw(NULL, tail, &pbs, "RR RDATA");
1192 /* done all sections */
1194 /* ??? is padding legal, or can we complain if more left in record? */
1196 /* process Answer Section again -- accept contents */
1198 pbs.cur = ans_start; /* go back to start of answer section */
1200 return process_answer_section(&pbs, TRUE, &dns_auth_level
1201 , qr_header.ancount, type, id, sgw_id);
1204 static int adns_in_flight = 0; /* queries outstanding */
1206 /* Start an asynchronous DNS query.
1208 * For KEY record, the result will be a list in "keys_from_dns".
1209 * For TXT records, the result will be a list in "gateways_from_dns".
1211 * If sgw_id is null, only consider TXT records that specify an
1212 * IP address for the gatway: we need this in the initiation case.
1214 * If sgw_id is non-null, only consider TXT records that specify
1215 * this id as the security gatway; this is useful to the Responder
1216 * for confirming claims of gateways.
1218 * Continuation cr gives information for continuing when the result shows up.
1220 * Two kinds of errors must be handled: synchronous (immediate)
1221 * and asynchronous. Synchronous errors are indicated by the returned
1222 * value of start_adns_query; in this case, the continuation will
1223 * have been freed and the continuation routine will not be called.
1224 * Asynchronous errors are indicated by the ugh parameter passed to the
1225 * continuation routine.
1227 * After the continuation routine has completed, handle_adns_answer
1228 * will free the continuation. The continuation routine should have
1229 * freed any axiliary resources.
1231 * Note: in the synchronous error case, start_adns_query will have
1232 * freed the continuation; this means that the caller will have to
1233 * be very careful to release any auxiliary resources that were in
1234 * the continuation record without using the continuation record.
1236 * Either there will be an error result passed to the continuation routine,
1237 * or the results will be in keys_from_dns or gatways_from_dns.
1238 * The result variables must by left NULL by the continutation routine.
1239 * The continuation routine is responsible for establishing and
1240 * disestablishing any logging context (whack_log_fd, cur_*).
1244 start_adns_query(const struct id *id /* domain to query */
1245 , const struct id *sgw_id /* if non-null, any accepted gw_info must match */
1246 , int type /* T_TXT or T_KEY, selecting rr type of interest */
1248 , struct adns_continuation *cr)
1251 const char *typename = rr_typename(type);
1253 /* Be sure that the result lists start out empty */
1254 passert(gateways_from_dns == NULL && keys_from_dns == NULL);
1256 cr->cont_fn = cont_fn;
1258 cr->sgw_specified = sgw_id != NULL;
1259 cr->sgw_id = cr->sgw_specified? *sgw_id : empty_id;
1261 memset(&cr->query, '\0', sizeof(cr->query));
1262 cr->query.len = sizeof(cr->query);
1263 cr->query.qmagic = ADNS_Q_MAGIC;
1264 cr->query.continuation = cr;
1267 err_t ugh = build_dns_name(cr->query.name_buf, id, typename);
1271 release_adns_continuation(cr);
1276 cr->query.type = type;
1278 /* write out query, perhaps a piece at a time */
1281 ssize_t m = write(adns_qfd
1282 , (unsigned char *)&cr->query + n, sizeof(cr->query) - n);
1288 log_errno((e, "error writing query to adns"));
1289 /* ??? how can we recover? */
1296 } while (n != sizeof(cr->query));
1298 unshare_id_content(&cr->id);
1299 unshare_id_content(&cr->sgw_id);
1307 handle_adns_answer(void)
1309 static size_t aalen = 0; /* bytes in answer buffer */
1310 static struct adns_answer a;
1313 passert(gateways_from_dns == NULL && keys_from_dns == NULL);
1314 passert(aalen < sizeof(a));
1315 n = read(adns_afd, (unsigned char *)&a + aalen, sizeof(a) - aalen);
1321 log_errno((e, "error reading answer from adns"));
1322 /* ??? how can we recover? */
1324 n = 0; /* now n reflects amount read */
1329 if (adns_in_flight != 0)
1331 log("EOF from adns with %d queries outstanding", adns_in_flight);
1332 /* ??? how can we recover? */
1336 log("EOF from adns with %lu bytes of a partial answer outstanding"
1337 , (unsigned long)aalen);
1338 /* ??? how can we recover? */
1344 passert(adns_in_flight > 0);
1349 while (aalen >= offsetof(struct adns_answer, ans) && aalen >= a.len)
1351 /* we've got a tasty answer -- process it */
1353 struct adns_continuation *cr = a.continuation;
1354 const char *typename = rr_typename(cr->query.type);
1355 const char *name_buf = cr->query.name_buf;
1360 /* newer resolvers support statp->res_h_errno as well as h_errno.
1361 * That might be better, but older resolvers don't.
1362 * See resolver(3), if you have it.
1363 * The undocumented(!) h_errno values are defined in
1364 * /usr/include/netdb.h.
1366 switch (a.h_errno_val)
1369 ugh = builddiag("no %s record for %s", typename, name_buf);
1371 case HOST_NOT_FOUND:
1372 ugh = builddiag("no host %s for %s record", name_buf, typename);
1375 ugh = builddiag("failure querying DNS for %s of %s: %s"
1376 , typename, name_buf, hstrerror(a.h_errno_val));
1380 else if (a.result > (int) sizeof(a.ans))
1382 ugh = builddiag("(INTERNAL ERROR) answer too long (%ld) for buffer"
1387 ugh = process_dns_answer(&cr->id
1388 , cr->sgw_specified? &cr->sgw_id : NULL
1389 , a.ans, a.result, cr->query.type);
1391 ugh = builddiag("failure processing %s record of DNS answer for %s: %s"
1392 , typename, name_buf, ugh);
1394 DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS,
1395 DBG_log(BLANK_FORMAT);
1397 DBG_log("asynch DNS answer for %s of %s", typename, name_buf);
1399 DBG_log("asynch DNS answer %s", ugh);
1402 passert(GLOBALS_ARE_RESET());
1403 cr->cont_fn(cr, ugh);
1405 release_adns_continuation(cr);
1407 /* shift out answer that we've consumed */
1409 memmove((unsigned char *)&a, (unsigned char *)&a + a.len, aalen);
1411 passert(gateways_from_dns == NULL && keys_from_dns == NULL);
1415 release_adns_continuation(struct adns_continuation *cr)
1417 passert(gateways_from_dns == NULL && keys_from_dns == NULL);
1418 unshare_id_content(&cr->id);
1419 unshare_id_content(&cr->sgw_id);