📄 dnskey.c
字号:
process_lwdnsq_key(u_char *str, enum dns_auth_level dns_auth_level, struct adns_continuation *const cr){ /* fields of KEY record. See RFC 2535 3.1 KEY RDATA format. */ unsigned long flags /* 16 bits */ , protocol /* 8 bits */ , algorithm; /* 8 bits */ char *rest = str , *p , *endofnumber; /* flags */ p = strsep(&rest, " \t"); if (p == NULL) return "lwdnsq KEY: missing flags"; flags = strtoul(p, &endofnumber, 10); if (*endofnumber != '\0') return "lwdnsq KEY: malformed flags"; /* protocol */ p = strsep(&rest, " \t"); if (p == NULL) return "lwdnsq KEY: missing protocol"; protocol = strtoul(p, &endofnumber, 10); if (*endofnumber != '\0') return "lwdnsq KEY: malformed protocol"; /* algorithm */ p = strsep(&rest, " \t"); if (p == NULL) return "lwdnsq KEY: missing algorithm"; algorithm = strtoul(p, &endofnumber, 10); if (*endofnumber != '\0') return "lwdnsq KEY: malformed algorithm"; /* is this key interesting? */ if (protocol == 4 /* IPSEC (RFC 2535 3.1.3) */ && algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */ && (flags & 0x8000ul) == 0 /* use for authentication (3.1.2) */ && (flags & 0x2CF0ul) == 0) /* must be zero */ { /* Decode base 64 encoding of key. * Similar code is in process_txt_rr_body. */ u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */ chunk_t kbc; err_t ugh = ttodatav(rest, 0, 64, kb, sizeof(kb), &kbc.len , diag_space, sizeof(diag_space), TTODATAV_IGNORESPACE); if (ugh != NULL) return builddiag("malformed key data: %s", ugh); if (kbc.len > sizeof(kb)) return builddiag("key data larger than %lu bytes" , (unsigned long) sizeof(kb)); kbc.ptr = kb; TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &kbc , &cr->keys_from_dns)); /* keep a reference to last one */ unreference_key(&cr->last_info); cr->last_info = reference_key(cr->keys_from_dns->key); } return NULL;}# endif /* USE_KEYRR */#else /* ! USE_LWRES *//* structure of Query Reply (RFC 1035 4.1.1): * * +---------------------+ * | Header | * +---------------------+ * | Question | the question for the name server * +---------------------+ * | Answer | RRs answering the question * +---------------------+ * | Authority | RRs pointing toward an authority * +---------------------+ * | Additional | RRs holding additional information * +---------------------+ *//* Header section format (as modified by RFC 2535 6.1): * 1 1 1 1 1 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | ID | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | QDCOUNT | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | ANCOUNT | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | NSCOUNT | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | ARCOUNT | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */struct qr_header { u_int16_t id; /* 16-bit identifier to match query */ u_int16_t stuff; /* packed crud: */#define QRS_QR 0x8000 /* QR: on if this is a response */#define QRS_OPCODE_SHIFT 11 /* OPCODE field */#define QRS_OPCODE_MASK 0xF#define QRSO_QUERY 0 /* standard query */#define QRSO_IQUERY 1 /* inverse query */#define QRSO_STATUS 2 /* server status request query */#define QRS_AA 0x0400 /* AA: on if Authoritative Answer */#define QRS_TC 0x0200 /* TC: on if truncation happened */#define QRS_RD 0x0100 /* RD: on if recursion desired */#define QRS_RA 0x0080 /* RA: on if recursion available */#define QRS_Z 0x0040 /* Z: reserved; must be zero */#define QRS_AD 0x0020 /* AD: on if authentic data (RFC 2535) */#define QRS_CD 0x0010 /* AD: on if checking disabled (RFC 2535) */#define QRS_RCODE_SHIFT 0 /* RCODE field: response code */#define QRS_RCODE_MASK 0xF#define QRSR_OK 0 u_int16_t qdcount; /* number of entries in question section */ u_int16_t ancount; /* number of resource records in answer section */ u_int16_t nscount; /* number of name server resource records in authority section */ u_int16_t arcount; /* number of resource records in additional records section */};static field_desc qr_header_fields[] = { { ft_nat, BYTES_FOR_BITS(16), "ID", NULL }, { ft_nat, BYTES_FOR_BITS(16), "stuff", NULL }, { ft_nat, BYTES_FOR_BITS(16), "QD Count", NULL }, { ft_nat, BYTES_FOR_BITS(16), "Answer Count", NULL }, { ft_nat, BYTES_FOR_BITS(16), "Authority Count", NULL }, { ft_nat, BYTES_FOR_BITS(16), "Additional Count", NULL }, { ft_end, 0, NULL, NULL }};static struct_desc qr_header_desc = { "Query Response Header", qr_header_fields, sizeof(struct qr_header)};/* Messages for codes in RCODE (see RFC 1035 4.1.1) */static const err_t rcode_text[QRS_RCODE_MASK + 1] = { NULL, /* not an error */ "Format error - The name server was unable to interpret the query", "Server failure - The name server was unable to process this query" " due to a problem with the name server", "Name Error - Meaningful only for responses from an authoritative name" " server, this code signifies that the domain name referenced in" " the query does not exist", "Not Implemented - The name server does not support the requested" " kind of query", "Refused - The name server refuses to perform the specified operation" " for policy reasons", /* the rest are reserved for future use */ };/* throw away a possibly compressed domain name */static err_teat_name(pb_stream *pbs){ u_char name_buf[NS_MAXDNAME + 2]; u_char *ip = pbs->cur; unsigned oi = 0; unsigned jump_count = 0; for (;;) { u_int8_t b; if (ip >= pbs->roof) return "ran out of message while skipping domain name"; b = *ip++; if (jump_count == 0) pbs->cur = ip; if (b == 0) break; switch (b & 0xC0) { case 0x00: /* we grab the next b characters */ if (oi + b > NS_MAXDNAME) return "domain name too long"; if (pbs->roof - ip <= b) return "domain name falls off end of message"; if (oi != 0) name_buf[oi++] = '.'; memcpy(name_buf + oi, ip, b); oi += b; ip += b; if (jump_count == 0) pbs->cur = ip; break; case 0xC0: { unsigned ix; if (ip >= pbs->roof) return "ran out of message in middle of compressed domain name"; ix = ((b & ~0xC0u) << 8) | *ip++; if (jump_count == 0) pbs->cur = ip; if (ix >= pbs_room(pbs)) return "impossible compressed domain name"; /* Avoid infinite loop. * There can be no more jumps than there are bytes * in the packet. Not a tight limit, but good enough. */ jump_count++; if (jump_count > pbs_room(pbs)) return "loop in compressed domain name"; ip = pbs->start + ix; } break; default: return "invalid code in label"; } } name_buf[oi++] = '\0'; DBG(DBG_DNS, DBG_log("skipping name %s", name_buf)); return NULL;}static err_teat_name_helpfully(pb_stream *pbs, const char *context){ err_t ugh = eat_name(pbs); return ugh == NULL? ugh : builddiag("malformed name within DNS record of %s: %s", context, ugh);}/* non-variable part of 4.1.2 Question Section entry: * 1 1 1 1 1 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | | * / QNAME / * / / * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | QTYPE | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | QCLASS | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */struct qs_fixed { u_int16_t qtype; u_int16_t qclass;};static field_desc qs_fixed_fields[] = { { ft_loose_enum, BYTES_FOR_BITS(16), "QTYPE", &rr_qtype_names }, { ft_loose_enum, BYTES_FOR_BITS(16), "QCLASS", &rr_class_names }, { ft_end, 0, NULL, NULL }};static struct_desc qs_fixed_desc = { "Question Section entry fixed part", qs_fixed_fields, sizeof(struct qs_fixed)};/* 4.1.3. Resource record format: * 1 1 1 1 1 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | | * / / * / NAME / * | | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | TYPE | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | CLASS | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | TTL | * | | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | RDLENGTH | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| * / RDATA / * / / * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */struct rr_fixed { u_int16_t type; u_int16_t class; u_int32_t ttl; /* actually signed */ u_int16_t rdlength;};static field_desc rr_fixed_fields[] = { { ft_loose_enum, BYTES_FOR_BITS(16), "type", &rr_type_names }, { ft_loose_enum, BYTES_FOR_BITS(16), "class", &rr_class_names }, { ft_nat, BYTES_FOR_BITS(32), "TTL", NULL }, { ft_nat, BYTES_FOR_BITS(16), "RD length", NULL }, { ft_end, 0, NULL, NULL }};static struct_desc rr_fixed_desc = { "Resource Record fixed part", rr_fixed_fields, /* note: following is tricky: avoids padding problems */ offsetof(struct rr_fixed, rdlength) + sizeof(u_int16_t)};/* RFC 1035 3.3.14: TXT RRs have text in the RDATA field. * It is in the form of a sequence of <character-string>s as described in 3.3. * unpack_txt_rdata() deals with this peculiar representation. *//* RFC 2535 3.1 KEY RDATA format: * * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | flags | protocol | algorithm | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | / * / public key / * / / * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| */struct key_rdata { u_int16_t flags; u_int8_t protocol; u_int8_t algorithm;};static field_desc key_rdata_fields[] = { { ft_nat, BYTES_FOR_BITS(16), "flags", NULL }, { ft_nat, BYTES_FOR_BITS(8), "protocol", NULL }, { ft_nat, BYTES_FOR_BITS(8), "algorithm", NULL }, { ft_end, 0, NULL, NULL }};static struct_desc key_rdata_desc = { "KEY RR RData fixed part", key_rdata_fields, sizeof(struct key_rdata)};/* RFC 2535 4.1 SIG RDATA format: * * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | type covered | algorithm | labels | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | original TTL | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | signature expiration | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | signature inception | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | key tag | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ signer's name + * | / * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-/ * / / * / signature / * / / * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */struct sig_rdata { u_int16_t type_covered; u_int8_t algorithm; u_int8_t labels; u_int32_t original_ttl; u_int32_t sig_expiration; u_int32_t sig_inception; u_int16_t key_tag;};static field_desc sig_rdata_fields[] = { { ft_nat, BYTES_FOR_BITS(16), "type_covered", NULL}, { ft_nat, BYTES_FOR_BITS(8), "algorithm", NULL}, { ft_nat, BYTES_FOR_BITS(8), "labels", NULL}, { ft_nat, BYTES_FOR_BITS(32), "original ttl", NULL}, { ft_nat, BYTES_FOR_BITS(32), "sig expiration", NULL}, { ft_nat, BYTES_FOR_BITS(32), "sig inception", NULL}, { ft_nat, BYTES_FOR_BITS(16), "key tag", NULL}, { ft_end, 0, NULL, NULL }};static struct_desc sig_rdata_desc = { "SIG RR RData fixed part", sig_rdata_fields, sizeof(struct sig_rdata)};/* handle a KEY Resource Record. */#ifdef USE_KEYRRstatic err_tprocess_key_rr(u_char *ptr, size_t len, bool doit /* should we capture information? */, enum dns_auth_level dns_auth_level, struct adns_continuation *const cr){ pb_stream pbs; struct key_rdata kr; if (len < sizeof(struct key_rdata)) return "KEY Resource Record's RD Length is too small"; init_pbs(&pbs, ptr, len, "KEY RR"); if (!in_struct(&kr, &key_rdata_desc, &pbs, NULL)) return "failed to get fixed part of KEY Resource Record RDATA"; if (kr.protocol == 4 /* IPSEC (RFC 2535 3.1.3) */ && kr.algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */ && (kr.flags & 0x8000) == 0 /* use for authentication (3.1.2) */ && (kr.flags & 0x2CF0) == 0) /* must be zero */ { /* we have what seems to be a tasty key */ if (doit) { chunk_t k; setchunk(k, pbs.cur, pbs_left(&pbs)); TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &k , &cr->keys_from_dns)); } } return NULL;}#endif /* USE_KEYRR *//* unpack TXT rr RDATA into C string. * A sequence of <character-string>s as described in RFC 1035 3.3. * We concatenate them. */static err_tunpack_txt_rdata(u_char *d, size_t dlen, const u_char *s, size_t slen){ size_t i = 0 , o = 0; while (i < slen) { size_t cl = s[i++]; if (i + cl > slen) return "TXT rr RDATA representation malformed"; if (o + cl >= dlen) return "TXT rr RDATA too large"; memcpy(d + o, s + i, cl); i += cl; o += cl; } d[o] = '\0'; if (strlen(d) != o) return "TXT rr RDATA contains a NUL"; return NULL;}static err_tprocess_txt_rr(u_char *rdata, size_t rdlen, bool doit /* should we capture information? */, enum dns_auth_level dns_auth_level, struct adns_continuation *const cr){ u_char str[RSA_MAX_ENCODING_BYTES * 8 / 6 + 200]; /* space for unpacked RDATA */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -