Commit Diff
Diff:
dc0f2d43090a04270cdfa09b6b8b449e6252813b
6f87dc2b46b3cbfb71320f535b34a0bb0734604c
Commit:
6f87dc2b46b3cbfb71320f535b34a0bb0734604c
Tree:
ba8ce3762990afc66c8abedfcdcdf4d94642311c
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Thu Jul 23 10:48:45 2020 UTC
Message:
add RP, HINFO, and CAA RR's This unearthed a few bugs. 1. in the forwarding engine (I'll have to look at that later) 2. in util's bitmask2human() function which blew up on CAA, it was a simple fix though. 255->256. The reason this was unearthed now is that CAA is type number 257, and thus above 255/256 which we've never been so high. This was checked through RFC 4034 section 4.1.2 Tested on OpenBSD/amd64 and octeon
blob - 584d16560c0e989195e86677bcd967dcf3831862
blob + d777b07fae2d04a6605b6641061acdc8b39052cc
--- dddctl.c
+++ dddctl.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: dddctl.c,v 1.113 2020/07/17 05:40:18 pjp Exp $
+ * $Id: dddctl.c,v 1.114 2020/07/23 10:48:45 pjp Exp $
*/
#include <sys/types.h>
@@ -840,6 +840,47 @@ print_rbt_bind(FILE *of, struct rbtree *rbt)
fprintf(of, "\"\t%s\n", (((struct naptr *)rrp2->rdata)->replacement[0] == '\0') ? "." : convert_name(((struct naptr *)rrp2->rdata)->replacement, ((struct naptr *)rrp2->rdata)->replacementlen));
}
}
+ if ((rrset = find_rr(rbt, DNS_TYPE_CAA)) != NULL) {
+ if ((rrp = TAILQ_FIRST(&rrset->rr_head)) == NULL) {
+ dolog(LOG_INFO, "no caa in zone!\n");
+ return -1;
+ }
+ TAILQ_FOREACH(rrp2, &rrset->rr_head, entries) {
+ fprintf(of, "%s %d IN CAA %d ",
+ convert_name(rbt->zone, rbt->zonelen),
+ rrset->ttl,
+ ((struct caa *)rrp2->rdata)->flags);
+
+ for (i = 0; i < ((struct caa *)rrp2->rdata)->taglen; i++) {
+ fprintf(of, "%c", ((struct caa *)rrp2->rdata)->tag[i]);
+ }
+ fprintf(of, " \"");
+ for (i = 0; i < ((struct caa *)rrp2->rdata)->valuelen; i++) {
+ fprintf(of, "%c", ((struct caa *)rrp2->rdata)->value[i]);
+ }
+ fprintf(of, "\"\n");
+ }
+ }
+ if ((rrset = find_rr(rbt, DNS_TYPE_HINFO)) != NULL) {
+ if ((rrp = TAILQ_FIRST(&rrset->rr_head)) == NULL) {
+ dolog(LOG_INFO, "no hinfo in zone!\n");
+ return -1;
+ }
+ TAILQ_FOREACH(rrp2, &rrset->rr_head, entries) {
+ fprintf(of, "%s %d IN HINFO ",
+ convert_name(rbt->zone, rbt->zonelen),
+ rrset->ttl);
+
+ for (i = 0; i < ((struct hinfo *)rrp2->rdata)->cpulen; i++) {
+ fprintf(of, "%c", ((struct hinfo *)rrp2->rdata)->cpu[i]);
+ }
+ fprintf(of, " ");
+ for (i = 0; i < ((struct hinfo *)rrp2->rdata)->oslen; i++) {
+ fprintf(of, "%c", ((struct hinfo *)rrp2->rdata)->os[i]);
+ }
+ fprintf(of, "\n");
+ }
+ }
if ((rrset = find_rr(rbt, DNS_TYPE_TXT)) != NULL) {
if ((rrp = TAILQ_FIRST(&rrset->rr_head)) == NULL) {
dolog(LOG_INFO, "no txt in zone!\n");
@@ -954,6 +995,20 @@ print_rbt_bind(FILE *of, struct rbtree *rbt)
((struct dnskey *)rrp2->rdata)->protocol,
((struct dnskey *)rrp2->rdata)->algorithm,
buf);
+ }
+ }
+ if ((rrset = find_rr(rbt, DNS_TYPE_RP)) != NULL) {
+ if ((rrp = TAILQ_FIRST(&rrset->rr_head)) == NULL) {
+ dolog(LOG_INFO, "no RP RR in zone!\n");
+ return -1;
+ }
+ TAILQ_FOREACH(rrp2, &rrset->rr_head, entries) {
+
+ fprintf(of, "%s %d IN RP %s %s\n",
+ convert_name(rbt->zone, rbt->zonelen),
+ rrset->ttl,
+ convert_name(((struct rp *)rrp2->rdata)->mbox, ((struct rp *)rrp2->rdata)->mboxlen),
+ convert_name(((struct rp *)rrp2->rdata)->txt, ((struct rp *)rrp2->rdata)->txtlen));
}
}
if ((rrset = find_rr(rbt, DNS_TYPE_NSEC3PARAM)) != NULL) {
blob - a3b91490e44e3c5643b5ed1c928339309b98e36c
blob + 6ce879ca0a69d039f5c748567f584e9822a0ca54
--- delphinusdnsd.c
+++ delphinusdnsd.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: delphinusdnsd.c,v 1.133 2020/07/21 18:19:58 pjp Exp $
+ * $Id: delphinusdnsd.c,v 1.134 2020/07/23 10:48:45 pjp Exp $
*/
@@ -155,6 +155,9 @@ extern int reply_txt(struct sreply *, int *, ddDB *);
extern int reply_version(struct sreply *, int *, ddDB *);
extern int reply_rrsig(struct sreply *, int *, ddDB *);
extern int reply_dnskey(struct sreply *, int *, ddDB *);
+extern int reply_caa(struct sreply *, int *, ddDB *);
+extern int reply_rp(struct sreply *, int *, ddDB *);
+extern int reply_hinfo(struct sreply *, int *, ddDB *);
extern int reply_ds(struct sreply *, int *, ddDB *);
extern int reply_nsec(struct sreply *, int *, ddDB *);
extern int reply_nsec3(struct sreply *, int *, ddDB *);
@@ -231,6 +234,9 @@ static struct reply_logic rlogic[] = {
{ DNS_TYPE_NSEC3, DNS_TYPE_NSEC3, BUILD_OTHER, reply_nsec3 },
{ DNS_TYPE_NSEC, DNS_TYPE_NSEC, BUILD_OTHER, reply_nsec },
{ DNS_TYPE_RRSIG, DNS_TYPE_RRSIG, BUILD_OTHER, reply_rrsig },
+ { DNS_TYPE_CAA, DNS_TYPE_CAA, BUILD_OTHER, reply_caa },
+ { DNS_TYPE_RP, DNS_TYPE_RP, BUILD_OTHER, reply_rp },
+ { DNS_TYPE_HINFO, DNS_TYPE_HINFO, BUILD_OTHER, reply_hinfo },
{ 0, 0, 0, NULL }
};
blob - dee407632cac56d338a2ce350ac7e6077ebfbf3b
blob + f2166a0935b291953cead7bc88910b70810bfec7
--- parse.y
+++ parse.y
@@ -21,7 +21,7 @@
*/
/*
- * $Id: parse.y,v 1.108 2020/07/17 05:40:19 pjp Exp $
+ * $Id: parse.y,v 1.109 2020/07/23 10:48:45 pjp Exp $
*/
%{
@@ -223,6 +223,9 @@ int fill_nsec(ddDB *, char *, char *, u_int32_t, cha
int fill_nsec3param(ddDB *, char *, char *, u_int32_t, u_int8_t, u_int8_t, u_int16_t, char *);
int fill_nsec3(ddDB *, char *, char *, u_int32_t, u_int8_t, u_int8_t, u_int16_t, char *, char *, char *);
int fill_ds(ddDB *, char *, char *, u_int32_t, u_int16_t, u_int8_t, u_int8_t, char *);
+int fill_rp(ddDB *, char *, char *, int, char *, char *);
+int fill_hinfo(ddDB *, char *, char *, int, char *, char *);
+int fill_caa(ddDB *, char *, char *, int, uint8_t, char *, char *);
void create_nsec_bitmap(char *, char *, int *);
int findeol(void);
@@ -1180,6 +1183,81 @@ zonestatement:
free ($15);
free ($17);
}
+ |
+ STRING COMMA STRING COMMA NUMBER COMMA NUMBER COMMA STRING COMMA QUOTEDSTRING CRLF
+ {
+ if (strcasecmp($3, "caa") == 0) {
+ if (fill_caa(mydb, $1, $3, $5, $7, $9, $11) < 0) {
+ return -1;
+ }
+
+#if DEBUG
+ if (debug)
+ printf("%s CAA -> %lld %s \"%s\"\n", $1, $7, $9, $11);
+#endif
+
+ } else {
+ if (debug)
+ printf("another record I don't know about?");
+ return (-1);
+ }
+
+ free ($1);
+ free ($3);
+ free ($9);
+ free ($11);
+
+ }
+ |
+ STRING COMMA STRING COMMA NUMBER COMMA QUOTEDSTRING COMMA QUOTEDSTRING CRLF
+ {
+ /* HINFO */
+ if (strcasecmp($3, "hinfo") == 0) {
+ if (fill_hinfo(mydb, $1, $3, $5, $7, $9) < 0) {
+ return -1;
+ }
+
+#if DEBUG
+ if (debug)
+ printf("%s HINFO -> \"%s\" \"%s\"\n", $1, $7, $9);
+#endif
+
+ } else {
+ if (debug)
+ printf("another record I don't know about?");
+ return (-1);
+ }
+
+ free ($1);
+ free ($3);
+ free ($7);
+ free ($9);
+ }
+ |
+ STRING COMMA STRING COMMA NUMBER COMMA STRING COMMA STRING CRLF
+ {
+ /* RP */
+ if (strcasecmp($3, "rp") == 0) {
+ if (fill_rp(mydb, $1, $3, $5, $7, $9) < 0) {
+ return -1;
+ }
+
+#if DEBUG
+ if (debug)
+ printf("%s RP -> %s %s\n", $1, $7, $9);
+#endif
+
+ } else {
+ if (debug)
+ printf("another record I don't know about?");
+ return (-1);
+ }
+
+ free ($1);
+ free ($3);
+ free ($7);
+ free ($9);
+ }
| comment CRLF
;
@@ -3196,6 +3274,161 @@ fill_ns(ddDB *db, char *name, char *type, int myttl, c
return (0);
+}
+
+int
+fill_caa(ddDB *db, char *name, char *type, int myttl, uint8_t flags, char *tag, char *value)
+{
+ struct caa *caa;
+ struct rbtree *rbt;
+ char *converted_name;
+ int converted_namelen;
+ int i;
+
+ for (i = 0; i < strlen(name); i++) {
+ name[i] = tolower((int)name[i]);
+ }
+
+ if (strlen(tag) > DNS_MAXNAME || strlen(value) > 1024) {
+ dolog(LOG_INFO, "input too long\n");
+ return -1;
+ }
+
+ converted_name = check_rr(name, type, DNS_TYPE_CAA, &converted_namelen);
+ if (converted_name == NULL) {
+ return -1;
+ }
+
+ if ((caa = (struct caa *)calloc(1, sizeof(struct caa))) == NULL) {
+ dolog(LOG_ERR, "calloc: %s\n", strerror(errno));
+ return -1;
+ }
+
+ caa->flags = flags;
+ caa->taglen = strlen(tag);
+ caa->valuelen = strlen(value);
+
+ memcpy(caa->value, value, caa->valuelen);
+ memcpy(caa->tag, tag, caa->taglen);
+
+ rbt = create_rr(db, converted_name, converted_namelen, DNS_TYPE_CAA, caa, myttl, 0);
+ if (rbt == NULL) {
+ dolog(LOG_ERR, "create_rr failed\n");
+ return -1;
+ }
+
+ free (converted_name);
+
+
+ return (0);
+}
+
+int
+fill_hinfo(ddDB *db, char *name, char *type, int myttl, char *cpu, char *os)
+{
+ struct hinfo *hi;
+ struct rbtree *rbt;
+ char *converted_name;
+ int converted_namelen;
+ int i, oslen, cpulen;
+
+ for (i = 0; i < strlen(name); i++) {
+ name[i] = tolower((int)name[i]);
+ }
+
+ if ((hi = (struct hinfo *)calloc(1, sizeof(struct hinfo))) == NULL) {
+ dolog(LOG_ERR, "calloc: %s\n", strerror(errno));
+ return -1;
+ }
+
+ converted_name = check_rr(name, type, DNS_TYPE_HINFO, &converted_namelen);
+ if (converted_name == NULL) {
+ return -1;
+ }
+
+
+ oslen = strlen(os);
+ cpulen = strlen(cpu);
+
+ if (oslen > 255 || cpulen > 255)
+ return -1;
+
+ hi->cpulen = cpulen;
+ hi->oslen = oslen;
+
+ memcpy(&hi->cpu[0], cpu, cpulen);
+ memcpy(&hi->os[0], os, oslen);
+
+ rbt = create_rr(db, converted_name, converted_namelen, DNS_TYPE_HINFO, hi, myttl, 0);
+ if (rbt == NULL) {
+ dolog(LOG_ERR, "create_rr failed\n");
+ return -1;
+ }
+
+ if (converted_name)
+ free (converted_name);
+
+
+ return (0);
+
+}
+
+int
+fill_rp(ddDB *db, char *name, char *type, int myttl, char *mbox, char *txt)
+{
+ struct rp *rp;
+ struct rbtree *rbt;
+ char *converted_name;
+ int converted_namelen;
+ int converted_mboxlen, converted_txtlen;
+ char *converted_mbox, *converted_txt;
+ int i;
+
+ for (i = 0; i < strlen(name); i++) {
+ name[i] = tolower((int)name[i]);
+ }
+
+ if ((rp = (struct rp *)calloc(1, sizeof(struct rp))) == NULL) {
+ dolog(LOG_ERR, "calloc: %s\n", strerror(errno));
+ return -1;
+ }
+
+ converted_name = check_rr(name, type, DNS_TYPE_RP, &converted_namelen);
+ if (converted_name == NULL) {
+ return -1;
+ }
+
+ converted_mbox = dns_label(mbox, &converted_mboxlen);
+ converted_txt = dns_label(txt, &converted_txtlen);
+
+ if (converted_mbox == NULL || converted_txt == NULL) {
+ dolog(LOG_INFO, "wrong input on dnsname (dns_label)\n");
+ return -1;
+ }
+
+ if (converted_mboxlen > DNS_MAXNAME || converted_txtlen > DNS_MAXNAME) {
+ dolog(LOG_INFO, "input names too long\n");
+ return -1;
+ }
+
+ memcpy(rp->mbox, converted_mbox, converted_mboxlen);
+ memcpy(rp->txt, converted_txt, converted_txtlen);
+ rp->txtlen = converted_txtlen;
+ rp->mboxlen = converted_mboxlen;
+
+ rbt = create_rr(db, converted_name, converted_namelen, DNS_TYPE_RP, rp, myttl, 0);
+ if (rbt == NULL) {
+ dolog(LOG_ERR, "create_rr failed\n");
+ return -1;
+ }
+
+ if (converted_name)
+ free (converted_name);
+
+ free (converted_mbox);
+ free (converted_txt);
+
+ return (0);
}
int
blob - cadd7423b622b0d54d689d6d1588de77ce6bfd42
blob + 25910e783e4270ed096c42a94a0b5772a2ba0ae8
--- raxfr.c
+++ raxfr.c
@@ -26,7 +26,7 @@
*
*/
/*
- * $Id: raxfr.c,v 1.55 2020/07/08 12:29:02 pjp Exp $
+ * $Id: raxfr.c,v 1.56 2020/07/23 10:48:45 pjp Exp $
*/
#include <sys/types.h>
@@ -100,6 +100,9 @@ int raxfr_a(FILE *, u_char *, u_char *, u_char *, stru
int raxfr_aaaa(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
int raxfr_cname(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
int raxfr_ns(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
+int raxfr_caa(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
+int raxfr_rp(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
+int raxfr_hinfo(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
int raxfr_ptr(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
int raxfr_mx(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
int raxfr_txt(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
@@ -202,6 +205,9 @@ static struct raxfr_logic supported[] = {
{ DNS_TYPE_TLSA, 0, raxfr_tlsa },
{ DNS_TYPE_SRV, 0, raxfr_srv },
{ DNS_TYPE_NAPTR, 0, raxfr_naptr },
+ { DNS_TYPE_RP, 0, raxfr_rp },
+ { DNS_TYPE_HINFO, 0, raxfr_hinfo },
+ { DNS_TYPE_CAA, 0, raxfr_caa },
{ 0, 0, NULL }
};
@@ -527,6 +533,84 @@ raxfr_rrsig(FILE *f, u_char *p, u_char *estart, u_char
}
int
+raxfr_caa(FILE *f, u_char *p, u_char *estart, u_char *end, struct soa *mysoa, u_int16_t rdlen, HMAC_CTX *ctx)
+{
+ struct caa caa;
+ u_char *q = p;
+ int i;
+
+ BOUNDS_CHECK((p + 1), q, rdlen, end);
+ caa.flags = *p;
+ p++;
+ BOUNDS_CHECK((p + 1), q, rdlen, end);
+ caa.taglen = *p;
+ p++;
+ BOUNDS_CHECK((p + caa.taglen), q, rdlen, end);
+ memcpy(&caa.tag, p, caa.taglen);
+ p += caa.taglen;
+ BOUNDS_CHECK((p + (rdlen - 2 - caa.taglen)), q, rdlen, end);
+ caa.valuelen = rdlen - 2 - caa.taglen;
+ memcpy(&caa.value, p, caa.valuelen);
+ p += caa.valuelen;
+
+ if (f != NULL) {
+ fprintf(f, "%u,", caa.flags);
+ for (i = 0; i < caa.taglen; i++) {
+ fprintf(f, "%c", caa.tag[i]);
+ }
+ fprintf(f, ",\"");
+ for (i = 0; i < caa.valuelen; i++) {
+ fprintf(f, "%c", caa.value[i]);
+ }
+ fprintf(f, "\"\n");
+ }
+
+ if (ctx != NULL)
+ HMAC_Update(ctx, q, p - q);
+
+ return (p - estart);
+}
+
+
+int
+raxfr_hinfo(FILE *f, u_char *p, u_char *estart, u_char *end, struct soa *mysoa, u_int16_t rdlen, HMAC_CTX *ctx)
+{
+ struct hinfo hinfo;
+ u_char *q = p;
+ int i;
+
+ BOUNDS_CHECK((p + 1), q, rdlen, end);
+ hinfo.cpulen = *p;
+ p++;
+ BOUNDS_CHECK((p + hinfo.cpulen), q, rdlen, end);
+ memcpy(&hinfo.cpu, p, hinfo.cpulen);
+ p += hinfo.cpulen;
+ BOUNDS_CHECK((p + 1), q, rdlen, end);
+ hinfo.oslen = *p;
+ p++;
+ BOUNDS_CHECK((p + hinfo.oslen), q, rdlen, end);
+ memcpy(&hinfo.os, p, hinfo.oslen);
+ p += hinfo.oslen;
+
+ if (f != NULL) {
+ fprintf(f, "\"");
+ for (i = 0; i < hinfo.cpulen; i++) {
+ fprintf(f, "%c", hinfo.cpu[i]);
+ }
+ fprintf(f, "\",\"");
+ for (i = 0; i < hinfo.oslen; i++) {
+ fprintf(f, "%c", hinfo.os[i]);
+ }
+ fprintf(f, "\"\n");
+ }
+
+ if (ctx != NULL)
+ HMAC_Update(ctx, q, p - q);
+
+ return (p - estart);
+}
+
+int
raxfr_ds(FILE *f, u_char *p, u_char *estart, u_char *end, struct soa *mysoa, u_int16_t rdlen, HMAC_CTX *ctx)
{
struct ds d;
@@ -825,6 +909,67 @@ raxfr_txt(FILE *f, u_char *p, u_char *estart, u_char *
HMAC_Update(ctx, q, p - q);
return (p - estart);
+}
+
+int
+raxfr_rp(FILE *f, u_char *p, u_char *estart, u_char *end, struct soa *mysoa, u_int16_t rdlen, HMAC_CTX *ctx)
+{
+ char *save, *humanname;
+ u_char *q = p;
+ u_char expand[256];
+ int max = sizeof(expand);
+ int elen = 0;
+
+ memset(&expand, 0, sizeof(expand));
+ save = expand_compression(q, estart, end, (u_char *)&expand, &elen, max);
+ if (save == NULL) {
+ fprintf(stderr, "expanding compression failure 2\n");
+ return -1;
+ } else {
+ q = save;
+ }
+
+ humanname = convert_name(expand, elen);
+ if (humanname == NULL) {
+ return -1;
+ }
+
+ if (f != NULL) {
+ fprintf(f, "%s,", humanname);
+ }
+
+ free(humanname);
+
+ memset(&expand, 0, sizeof(expand));
+ elen = 0;
+ save = expand_compression(q, estart, end, (u_char *)&expand, &elen, max);
+ if (save == NULL) {
+ fprintf(stderr, "expanding compression failure 2\n");
+ return -1;
+ } else {
+ q = save;
+ }
+
+ humanname = convert_name(expand, elen);
+ if (humanname == NULL) {
+ return -1;
+ }
+
+ if (f != NULL) {
+ fprintf(f, "%s\n", humanname);
+ }
+
+ free(humanname);
+
+
+
+
+
+ if (ctx != NULL) {
+ HMAC_Update(ctx, p, q - p);
+ }
+
+ return (q - estart);
}
int
blob - e7fd27c26f5585b6fb468c7fb4bb4f326281cc01
blob + 58030fccb566edfd0891b98015f0a85d87fb92c8
--- reply.c
+++ reply.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: reply.c,v 1.110 2020/07/21 18:19:58 pjp Exp $
+ * $Id: reply.c,v 1.111 2020/07/23 10:48:45 pjp Exp $
*/
#include <sys/types.h>
@@ -112,6 +112,9 @@ extern int dn_contains(char *, int, char *, int);
u_int16_t create_anyreply(struct sreply *, char *, int, int, int);
+int reply_caa(struct sreply *, int *, ddDB *);
+int reply_hinfo(struct sreply *, int *, ddDB *);
+int reply_rp(struct sreply *, int *, ddDB *);
int reply_generic(struct sreply *, int *, ddDB *);
int reply_a(struct sreply *, int *, ddDB *);
int reply_nsec3(struct sreply *, int *, ddDB *);
@@ -798,6 +801,599 @@ out:
return (retlen);
}
+/*
+ * REPLY_CAA
+ */
+
+int
+reply_caa(struct sreply *sreply, int *sretlen, ddDB *db)
+{
+ char *reply = sreply->replybuf;
+ struct dns_header *odh;
+ u_int16_t outlen = 0;
+ int caa_count;
+
+ struct answer {
+ char name[2];
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl;
+ u_int16_t rdlength; /* 12 */
+ } __attribute__((packed));
+
+ struct answer *answer;
+
+ int so = sreply->so;
+ char *buf = sreply->buf;
+ int len = sreply->len;
+ struct question *q = sreply->q;
+ struct sockaddr *sa = sreply->sa;
+ int salen = sreply->salen;
+ struct rbtree *rbt = sreply->rbt1;
+ struct rrset *rrset = NULL;
+ struct rr *rrp = NULL;
+
+ int istcp = sreply->istcp;
+ int replysize = 512;
+ int retlen = -1;
+ u_int16_t rollback;
+ int valuelen, taglen;
+ time_t now;
+
+
+ now = time(NULL);
+
+ if ((rrset = find_rr(rbt, DNS_TYPE_CAA)) == 0)
+ return -1;
+
+ if (istcp) {
+ replysize = 65535;
+ }
+
+ if (!istcp && q->edns0len > 512)
+ replysize = q->edns0len;
+
+ odh = (struct dns_header *)&reply[0];
+
+ outlen = sizeof(struct dns_header);
+
+ if (len > replysize) {
+ return (retlen);
+ }
+
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+
+ outlen += (q->hdr->namelen + 4);
+ rollback = outlen;
+
+ memset((char *)&odh->query, 0, sizeof(u_int16_t));
+ set_reply_flags(rbt, odh, q);
+
+ odh->question = htons(1);
+ odh->answer = htons(1);
+ odh->nsrr = 0;
+ odh->additional = 0;
+
+ /* skip dns header, question name, qtype and qclass */
+ answer = (struct answer *)(&reply[0] + sizeof(struct dns_header) +
+ q->hdr->namelen + 4);
+
+ caa_count = 0;
+
+ TAILQ_FOREACH(rrp, &rrset->rr_head, entries) {
+ if ((outlen + sizeof(struct answer) + 2 + \
+ ((struct caa *)rrp->rdata)->taglen + \
+ ((struct caa *)rrp->rdata)->valuelen) > replysize) {
+
+ NTOHS(odh->query);
+ SET_DNS_TRUNCATION(odh);
+ HTONS(odh->query);
+ odh->answer = 0;
+ odh->nsrr = 0;
+ odh->additional = 0;
+ outlen = rollback;
+ goto out;
+ }
+
+ answer->name[0] = 0xc0; /* 1 byte */
+ answer->name[1] = 0x0c; /* 2 bytes */
+ answer->type = q->hdr->qtype; /* 4 bytes */
+ answer->class = q->hdr->qclass; /* 6 bytes */
+
+ if (q->aa)
+ answer->ttl = htonl(rrset->ttl); /* 10 b */
+ else
+ answer->ttl = htonl(rrset->ttl - (MIN(rrset->ttl, difftime(now, rrset->created))));
+
+
+ caa_count++;
+ outlen += 12;
+
+ taglen = ((struct caa *)rrp->rdata)->taglen;
+ valuelen = ((struct caa *)rrp->rdata)->valuelen;
+
+ pack8(&reply[outlen++], ((struct caa *)rrp->rdata)->flags);
+ pack8(&reply[outlen++], taglen);
+ pack(&reply[outlen], ((struct caa *)rrp->rdata)->tag, taglen);
+ outlen += taglen;
+ pack(&reply[outlen],((struct caa *)rrp->rdata)->value,valuelen);
+ outlen += valuelen;
+
+ answer->rdlength = htons(2 + taglen + valuelen);
+
+ /* set new offset for answer */
+ answer = (struct answer *)&reply[outlen];
+ }
+
+ odh->answer = htons(caa_count);
+
+
+ /* Add RRSIG reply_nsec */
+ if (dnssec && q->dnssecok && (rbt->flags & RBT_DNSSEC)) {
+ int tmplen = 0;
+ int origlen = outlen;
+ int retcount;
+
+ tmplen = additional_rrsig(q->hdr->name, q->hdr->namelen, DNS_TYPE_CAA, rbt, reply, replysize, outlen, &retcount, q->aa);
+
+ if (tmplen == 0) {
+
+ /* we're forwarding and had no RRSIG return with -1 */
+ if (q->aa != 1)
+ return -1;
+
+ NTOHS(odh->query);
+ SET_DNS_TRUNCATION(odh);
+ HTONS(odh->query);
+ odh->answer = 0;
+ odh->nsrr = 0;
+ odh->additional = 0;
+ outlen = rollback;
+ goto out;
+ }
+
+ outlen = tmplen;
+
+ if (outlen > origlen)
+ odh->answer = htons(caa_count + retcount);
+
+ }
+
+out:
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ odh->additional = htons(1);
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
+ if (q->tsig.tsigverified == 1) {
+ outlen = additional_tsig(q, reply, replysize, outlen, 0, 0, NULL);
+
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+ }
+
+ if (istcp) {
+ char *tmpbuf;
+
+ tmpbuf = malloc(outlen + 2);
+ if (tmpbuf == 0) {
+ dolog(LOG_INFO, "malloc: %s\n", strerror(errno));
+ }
+ pack16(tmpbuf, htons(outlen));
+ memcpy(&tmpbuf[2], reply, outlen);
+
+ if ((retlen = send(so, tmpbuf, outlen + 2, 0)) < 0) {
+ dolog(LOG_INFO, "send: %s\n", strerror(errno));
+ }
+ free(tmpbuf);
+ } else {
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
+ }
+ }
+
+
+ return (retlen);
+}
+
+int
+reply_hinfo(struct sreply *sreply, int *sretlen, ddDB *db)
+{
+ char *reply = sreply->replybuf;
+ struct dns_header *odh;
+ u_int16_t outlen = 0;
+ int hinfo_count;
+
+ struct answer {
+ char name[2];
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl;
+ u_int16_t rdlength; /* 12 */
+ } __attribute__((packed));
+
+ struct answer *answer;
+
+ int so = sreply->so;
+ char *buf = sreply->buf;
+ int len = sreply->len;
+ struct question *q = sreply->q;
+ struct sockaddr *sa = sreply->sa;
+ int salen = sreply->salen;
+ struct rbtree *rbt = sreply->rbt1;
+ struct rrset *rrset = NULL;
+ struct rr *rrp = NULL;
+
+ int istcp = sreply->istcp;
+ int replysize = 512;
+ int retlen = -1;
+ u_int16_t rollback;
+ time_t now;
+
+
+ now = time(NULL);
+
+ if ((rrset = find_rr(rbt, DNS_TYPE_HINFO)) == 0)
+ return -1;
+
+ if (istcp) {
+ replysize = 65535;
+ }
+
+ if (!istcp && q->edns0len > 512)
+ replysize = q->edns0len;
+
+ odh = (struct dns_header *)&reply[0];
+
+ outlen = sizeof(struct dns_header);
+
+ if (len > replysize) {
+ return (retlen);
+ }
+
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+
+ outlen += (q->hdr->namelen + 4);
+ rollback = outlen;
+
+ memset((char *)&odh->query, 0, sizeof(u_int16_t));
+ set_reply_flags(rbt, odh, q);
+
+ odh->question = htons(1);
+ odh->answer = htons(1);
+ odh->nsrr = 0;
+ odh->additional = 0;
+
+ /* skip dns header, question name, qtype and qclass */
+ answer = (struct answer *)(&reply[0] + sizeof(struct dns_header) +
+ q->hdr->namelen + 4);
+
+ hinfo_count = 0;
+
+ TAILQ_FOREACH(rrp, &rrset->rr_head, entries) {
+ if ((outlen + sizeof(struct answer) + 2 + \
+ ((struct hinfo *)rrp->rdata)->cpulen + \
+ ((struct hinfo *)rrp->rdata)->oslen) > replysize) {
+
+ NTOHS(odh->query);
+ SET_DNS_TRUNCATION(odh);
+ HTONS(odh->query);
+ odh->answer = 0;
+ odh->nsrr = 0;
+ odh->additional = 0;
+ outlen = rollback;
+ goto out;
+ }
+
+ answer->name[0] = 0xc0; /* 1 byte */
+ answer->name[1] = 0x0c; /* 2 bytes */
+ answer->type = q->hdr->qtype; /* 4 bytes */
+ answer->class = q->hdr->qclass; /* 6 bytes */
+
+ if (q->aa)
+ answer->ttl = htonl(rrset->ttl); /* 10 b */
+ else
+ answer->ttl = htonl(rrset->ttl - (MIN(rrset->ttl, difftime(now, rrset->created))));
+
+
+ hinfo_count++;
+ outlen += 12;
+
+ pack8(&reply[outlen++], ((struct hinfo *)rrp->rdata)->cpulen);
+ pack(&reply[outlen], ((struct hinfo *)rrp->rdata)->cpu,
+ ((struct hinfo *)rrp->rdata)->cpulen);
+ outlen += ((struct hinfo *)rrp->rdata)->cpulen;
+ pack8(&reply[outlen++], ((struct hinfo *)rrp->rdata)->oslen);
+ pack(&reply[outlen], ((struct hinfo *)rrp->rdata)->os,
+ ((struct hinfo *)rrp->rdata)->oslen);
+ outlen += ((struct hinfo *)rrp->rdata)->oslen;
+
+ answer->rdlength = htons(2 + \
+ ((struct hinfo *)rrp->rdata)->oslen + \
+ ((struct hinfo *)rrp->rdata)->cpulen);
+
+ /* set new offset for answer */
+ answer = (struct answer *)&reply[outlen];
+ }
+
+ odh->answer = htons(hinfo_count);
+
+
+ /* Add RRSIG reply_nsec */
+ if (dnssec && q->dnssecok && (rbt->flags & RBT_DNSSEC)) {
+ int tmplen = 0;
+ int origlen = outlen;
+ int retcount;
+
+ tmplen = additional_rrsig(q->hdr->name, q->hdr->namelen, DNS_TYPE_HINFO, rbt, reply, replysize, outlen, &retcount, q->aa);
+
+ if (tmplen == 0) {
+
+ /* we're forwarding and had no RRSIG return with -1 */
+ if (q->aa != 1)
+ return -1;
+
+ NTOHS(odh->query);
+ SET_DNS_TRUNCATION(odh);
+ HTONS(odh->query);
+ odh->answer = 0;
+ odh->nsrr = 0;
+ odh->additional = 0;
+ outlen = rollback;
+ goto out;
+ }
+
+ outlen = tmplen;
+
+ if (outlen > origlen)
+ odh->answer = htons(hinfo_count + retcount);
+
+ }
+
+out:
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ odh->additional = htons(1);
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
+ if (q->tsig.tsigverified == 1) {
+ outlen = additional_tsig(q, reply, replysize, outlen, 0, 0, NULL);
+
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+ }
+
+ if (istcp) {
+ char *tmpbuf;
+
+ tmpbuf = malloc(outlen + 2);
+ if (tmpbuf == 0) {
+ dolog(LOG_INFO, "malloc: %s\n", strerror(errno));
+ }
+ pack16(tmpbuf, htons(outlen));
+ memcpy(&tmpbuf[2], reply, outlen);
+
+ if ((retlen = send(so, tmpbuf, outlen + 2, 0)) < 0) {
+ dolog(LOG_INFO, "send: %s\n", strerror(errno));
+ }
+ free(tmpbuf);
+ } else {
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
+ }
+ }
+
+
+ return (retlen);
+}
+
+int
+reply_rp(struct sreply *sreply, int *sretlen, ddDB *db)
+{
+ char *reply = sreply->replybuf;
+ struct dns_header *odh;
+ u_int16_t outlen = 0;
+ int rp_count;
+
+ struct answer {
+ char name[2];
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl;
+ u_int16_t rdlength; /* 12 */
+ } __attribute__((packed));
+
+ struct answer *answer;
+
+ int so = sreply->so;
+ char *buf = sreply->buf;
+ int len = sreply->len;
+ struct question *q = sreply->q;
+ struct sockaddr *sa = sreply->sa;
+ int salen = sreply->salen;
+ struct rbtree *rbt = sreply->rbt1;
+ struct rrset *rrset = NULL;
+ struct rr *rrp = NULL;
+
+ int istcp = sreply->istcp;
+ int replysize = 512;
+ int retlen = -1;
+ u_int16_t rollback;
+ time_t now;
+
+
+ now = time(NULL);
+
+ if ((rrset = find_rr(rbt, DNS_TYPE_RP)) == 0)
+ return -1;
+
+ if (istcp) {
+ replysize = 65535;
+ }
+
+ if (!istcp && q->edns0len > 512)
+ replysize = q->edns0len;
+
+ odh = (struct dns_header *)&reply[0];
+
+ outlen = sizeof(struct dns_header);
+
+ if (len > replysize) {
+ return (retlen);
+ }
+
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+
+ outlen += (q->hdr->namelen + 4);
+ rollback = outlen;
+
+ memset((char *)&odh->query, 0, sizeof(u_int16_t));
+ set_reply_flags(rbt, odh, q);
+
+ odh->question = htons(1);
+ odh->answer = htons(1);
+ odh->nsrr = 0;
+ odh->additional = 0;
+
+ /* skip dns header, question name, qtype and qclass */
+ answer = (struct answer *)(&reply[0] + sizeof(struct dns_header) +
+ q->hdr->namelen + 4);
+
+ rp_count = 0;
+
+ TAILQ_FOREACH(rrp, &rrset->rr_head, entries) {
+ if ((outlen + sizeof(struct answer) + \
+ ((struct rp *)rrp->rdata)->mboxlen + \
+ ((struct rp *)rrp->rdata)->txtlen) > replysize) {
+
+ NTOHS(odh->query);
+ SET_DNS_TRUNCATION(odh);
+ HTONS(odh->query);
+ odh->answer = 0;
+ odh->nsrr = 0;
+ odh->additional = 0;
+ outlen = rollback;
+ goto out;
+ }
+
+ answer->name[0] = 0xc0; /* 1 byte */
+ answer->name[1] = 0x0c; /* 2 bytes */
+ answer->type = q->hdr->qtype; /* 4 bytes */
+ answer->class = q->hdr->qclass; /* 6 bytes */
+
+ if (q->aa)
+ answer->ttl = htonl(rrset->ttl); /* 10 b */
+ else
+ answer->ttl = htonl(rrset->ttl - (MIN(rrset->ttl, difftime(now, rrset->created))));
+
+
+ rp_count++;
+ outlen += 12;
+
+ pack(&reply[outlen], ((struct rp *)rrp->rdata)->mbox,
+ ((struct rp *)rrp->rdata)->mboxlen);
+ outlen += ((struct rp *)rrp->rdata)->mboxlen;
+
+ pack(&reply[outlen], ((struct rp *)rrp->rdata)->txt,
+ ((struct rp *)rrp->rdata)->txtlen);
+ outlen += ((struct rp *)rrp->rdata)->txtlen;
+
+ answer->rdlength = htons(((struct rp *)rrp->rdata)->mboxlen + \
+ ((struct rp *)rrp->rdata)->txtlen);
+
+ /* set new offset for answer */
+ answer = (struct answer *)&reply[outlen];
+ }
+
+ odh->answer = htons(rp_count);
+
+
+ /* Add RRSIG reply_nsec */
+ if (dnssec && q->dnssecok && (rbt->flags & RBT_DNSSEC)) {
+ int tmplen = 0;
+ int origlen = outlen;
+ int retcount;
+
+ tmplen = additional_rrsig(q->hdr->name, q->hdr->namelen, DNS_TYPE_RP, rbt, reply, replysize, outlen, &retcount, q->aa);
+
+ if (tmplen == 0) {
+
+ /* we're forwarding and had no RRSIG return with -1 */
+ if (q->aa != 1)
+ return -1;
+
+ NTOHS(odh->query);
+ SET_DNS_TRUNCATION(odh);
+ HTONS(odh->query);
+ odh->answer = 0;
+ odh->nsrr = 0;
+ odh->additional = 0;
+ outlen = rollback;
+ goto out;
+ }
+
+ outlen = tmplen;
+
+ if (outlen > origlen)
+ odh->answer = htons(rp_count + retcount);
+
+ }
+
+out:
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ odh->additional = htons(1);
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
+ if (q->tsig.tsigverified == 1) {
+ outlen = additional_tsig(q, reply, replysize, outlen, 0, 0, NULL);
+
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+ }
+
+ if (istcp) {
+ char *tmpbuf;
+
+ tmpbuf = malloc(outlen + 2);
+ if (tmpbuf == 0) {
+ dolog(LOG_INFO, "malloc: %s\n", strerror(errno));
+ }
+ pack16(tmpbuf, htons(outlen));
+ memcpy(&tmpbuf[2], reply, outlen);
+
+ if ((retlen = send(so, tmpbuf, outlen + 2, 0)) < 0) {
+ dolog(LOG_INFO, "send: %s\n", strerror(errno));
+ }
+ free(tmpbuf);
+ } else {
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
+ }
+ }
+
+
+ return (retlen);
+}
+
/*
* REPLY_NSEC() - replies a DNS question (*q) on socket (so)
*
@@ -5694,6 +6290,7 @@ create_anyreply(struct sreply *sreply, char *reply, in
int tlsa_count, typelen;
int ds_count, dnskey_count;
int naptr_count, rrsig_count;
+ int caa_count, rp_count, hinfo_count;
int tmplen;
struct answer {
u_int16_t type; /* 0 */
@@ -5914,6 +6511,161 @@ create_anyreply(struct sreply *sreply, char *reply, in
NTOHS(odh->answer);
odh->answer += dnskey_count;
HTONS(odh->answer);
+ }
+ if ((rrset = find_rr(rbt, DNS_TYPE_HINFO)) != 0) {
+ hinfo_count = 0;
+
+ TAILQ_FOREACH(rrp, &rrset->rr_head, entries) {
+ if (offset + q->hdr->namelen > rlen)
+ goto truncate;
+
+ memcpy(&reply[offset], q->hdr->name, q->hdr->namelen);
+ offset += q->hdr->namelen;
+
+ if ((tmplen = compress_label((u_char*)reply, offset, q->hdr->namelen)) > 0) {
+ offset = tmplen;
+ }
+
+ answer = (struct answer *)&reply[offset];
+
+ answer->type = htons(DNS_TYPE_HINFO);
+ answer->class = htons(DNS_CLASS_IN);
+
+ if (q->aa)
+ answer->ttl = htonl(rrset->ttl);
+ else
+ answer->ttl = htonl(rrset->ttl - (MIN(rrset->ttl, difftime(now, rrset->created))));
+
+ answer->rdlength = htons(namelen);
+
+ offset += 10; /* struct answer */
+
+ if ((offset + 2 + \
+ ((struct hinfo *)rrp->rdata)->oslen + \
+ ((struct hinfo *)rrp->rdata)->cpulen) > rlen)
+ goto truncate;
+
+ pack8(&reply[offset++], ((struct hinfo *)rrp->rdata)->cpulen);
+
+ pack(&reply[offset], ((struct hinfo *)rrp->rdata)->cpu,((struct hinfo *)rrp->rdata)->cpulen);
+ offset += ((struct hinfo *)rrp->rdata)->cpulen;
+
+ pack8(&reply[offset++], ((struct hinfo *)rrp->rdata)->oslen);
+ pack(&reply[offset], ((struct hinfo *)rrp->rdata)->os,((struct hinfo *)rrp->rdata)->oslen);
+ offset += ((struct hinfo *)rrp->rdata)->oslen;
+
+
+ answer->rdlength = htons(&reply[offset] - answer->rdata);
+
+ hinfo_count++;
+
+ NTOHS(odh->answer);
+ odh->answer += 1;
+ HTONS(odh->answer);
+
+ }
+ }
+ if ((rrset = find_rr(rbt, DNS_TYPE_RP)) != 0) {
+ rp_count = 0;
+
+ TAILQ_FOREACH(rrp, &rrset->rr_head, entries) {
+ if (offset + q->hdr->namelen > rlen)
+ goto truncate;
+
+ memcpy(&reply[offset], q->hdr->name, q->hdr->namelen);
+ offset += q->hdr->namelen;
+
+ if ((tmplen = compress_label((u_char*)reply, offset, q->hdr->namelen)) > 0) {
+ offset = tmplen;
+ }
+
+ answer = (struct answer *)&reply[offset];
+
+ answer->type = htons(DNS_TYPE_RP);
+ answer->class = htons(DNS_CLASS_IN);
+
+ if (q->aa)
+ answer->ttl = htonl(rrset->ttl);
+ else
+ answer->ttl = htonl(rrset->ttl - (MIN(rrset->ttl, difftime(now, rrset->created))));
+
+ answer->rdlength = htons(namelen);
+
+ offset += 10; /* struct answer */
+
+ if ((offset + \
+ ((struct rp *)rrp->rdata)->mboxlen + \
+ ((struct rp *)rrp->rdata)->txtlen) > rlen)
+ goto truncate;
+
+ pack(&reply[offset], ((struct rp *)rrp->rdata)->mbox,((struct rp *)rrp->rdata)->mboxlen);
+ offset += ((struct rp *)rrp->rdata)->mboxlen;
+
+ pack(&reply[offset], ((struct rp *)rrp->rdata)->txt,((struct rp *)rrp->rdata)->txtlen);
+ offset += ((struct rp *)rrp->rdata)->txtlen;
+
+
+ answer->rdlength = htons(&reply[offset] - answer->rdata);
+
+ rp_count++;
+
+ NTOHS(odh->answer);
+ odh->answer += 1;
+ HTONS(odh->answer);
+
+ }
+ }
+ if ((rrset = find_rr(rbt, DNS_TYPE_CAA)) != 0) {
+ caa_count = 0;
+
+ TAILQ_FOREACH(rrp, &rrset->rr_head, entries) {
+ if (offset + q->hdr->namelen > rlen)
+ goto truncate;
+
+ memcpy(&reply[offset], q->hdr->name, q->hdr->namelen);
+ offset += q->hdr->namelen;
+
+ if ((tmplen = compress_label((u_char*)reply, offset, q->hdr->namelen)) > 0) {
+ offset = tmplen;
+ }
+
+ answer = (struct answer *)&reply[offset];
+
+ answer->type = htons(DNS_TYPE_CAA);
+ answer->class = htons(DNS_CLASS_IN);
+
+ if (q->aa)
+ answer->ttl = htonl(rrset->ttl);
+ else
+ answer->ttl = htonl(rrset->ttl - (MIN(rrset->ttl, difftime(now, rrset->created))));
+
+ answer->rdlength = htons(namelen);
+
+ offset += 10; /* struct answer */
+
+ if ((offset + 2 + \
+ ((struct caa *)rrp->rdata)->taglen + \
+ ((struct caa *)rrp->rdata)->valuelen) > rlen)
+ goto truncate;
+
+ pack8(&reply[offset++], ((struct caa *)rrp->rdata)->flags);
+ pack8(&reply[offset++], ((struct caa *)rrp->rdata)->taglen);
+ pack(&reply[offset], ((struct caa *)rrp->rdata)->tag,((struct caa *)rrp->rdata)->taglen);
+ offset += ((struct caa *)rrp->rdata)->taglen;
+
+ pack(&reply[offset], ((struct caa *)rrp->rdata)->value,((struct caa *)rrp->rdata)->valuelen);
+ offset += ((struct caa *)rrp->rdata)->valuelen;
+
+
+ answer->rdlength = htons(&reply[offset] - answer->rdata);
+
+ caa_count++;
+
+ NTOHS(odh->answer);
+ odh->answer += 1;
+ HTONS(odh->answer);
+
+ }
}
if ((rrset = find_rr(rbt, DNS_TYPE_DS)) != 0) {
ds_count = 0;
blob - b0f84d2060a93509a59757052050fcc4540c541f
blob + 9ad4281c62cafcaaa39a2241ab0eea41f157d0e7
--- sign.c
+++ sign.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: sign.c,v 1.8 2020/07/16 17:54:03 pjp Exp $
+ * $Id: sign.c,v 1.9 2020/07/23 10:48:45 pjp Exp $
*/
#include <sys/types.h>
@@ -146,6 +146,9 @@ int alg_to_rsa(int);
int construct_nsec3(ddDB *, char *, int, char *);
int calculate_rrsigs(ddDB *, char *, int, int);
+static int sign_hinfo(ddDB *, char *, int, struct rbtree *, int);
+static int sign_rp(ddDB *, char *, int, struct rbtree *, int);
+static int sign_caa(ddDB *, char *, int, struct rbtree *, int);
static int sign_dnskey(ddDB *, char *, int, struct rbtree *, int);
static int sign_a(ddDB *, char *, int, struct rbtree *, int);
static int sign_mx(ddDB *, char *, int, struct rbtree *, int);
@@ -1746,8 +1749,25 @@ calculate_rrsigs(ddDB *db, char *zonename, int expiry,
return -1;
}
}
+ if ((rrset = find_rr(rbt, DNS_TYPE_CAA)) != NULL) {
+ if (sign_caa(db, zonename, expiry, rbt, rollmethod) < 0) {
+ fprintf(stderr, "sign_caa error\n");
+ return -1;
+ }
+ }
+ if ((rrset = find_rr(rbt, DNS_TYPE_RP)) != NULL) {
+ if (sign_rp(db, zonename, expiry, rbt, rollmethod) < 0) {
+ fprintf(stderr, "sign_rp error\n");
+ return -1;
+ }
+ }
+ if ((rrset = find_rr(rbt, DNS_TYPE_HINFO)) != NULL) {
+ if (sign_hinfo(db, zonename, expiry, rbt, rollmethod) < 0) {
+ fprintf(stderr, "sign_hinfo error\n");
+ return -1;
+ }
+ }
-
j++;
}
@@ -4082,7 +4102,709 @@ sign_tlsa(ddDB *db, char *zonename, int expiry, struct
return 0;
}
+static int
+sign_rp(ddDB *db, char *zonename, int expiry, struct rbtree *rbt, int rollmethod)
+{
+ struct rrset *rrset = NULL;
+ struct rr *rrp = NULL;
+ struct rr *rrp2 = NULL;
+ struct keysentry **zsk_key;
+
+ char tmp[4096];
+ char signature[4096];
+ char shabuf[64];
+
+
+ char *dnsname;
+ char *p, *q;
+ char *key, *tmpkey;
+ char *zone;
+
+ uint32_t ttl;
+ uint16_t flags;
+ uint8_t protocol;
+ uint8_t algorithm;
+
+ int labellen;
+ int keyid;
+ int len;
+ int keylen, siglen = sizeof(signature);
+ int labels;
+ int nzk = 0;
+
+ char timebuf[32];
+ struct tm tm;
+ u_int32_t expiredon2, signedon2;
+ TAILQ_HEAD(listhead, canonical) head;
+
+ struct canonical {
+ char *data;
+ int len;
+ TAILQ_ENTRY(canonical) entries;
+ } *c1, *c2, *cp;
+
+
+ TAILQ_INIT(&head);
+ memset(&shabuf, 0, sizeof(shabuf));
+
+ key = malloc(10 * 4096);
+ if (key == NULL) {
+ dolog(LOG_INFO, "key out of memory\n");
+ return -1;
+ }
+ tmpkey = malloc(10 * 4096);
+ if (tmpkey == NULL) {
+ dolog(LOG_INFO, "tmpkey out of memory\n");
+ return -1;
+ }
+
+ zsk_key = calloc(3, sizeof(struct keysentry *));
+ if (zsk_key == NULL) {
+ dolog(LOG_INFO, "out of memory\n");
+ return -1;
+ }
+
+ nzk = 0;
+ SLIST_FOREACH(knp, &keyshead, keys_entry) {
+ if ((knp->type == KEYTYPE_ZSK && rollmethod == \
+ ROLLOVER_METHOD_DOUBLE_SIGNATURE) || \
+ (knp->sign == 1 && knp->type == KEYTYPE_ZSK)) {
+ zsk_key[nzk++] = knp;
+ }
+ }
+
+ zsk_key[nzk] = NULL;
+
+ /* get the ZSK */
+ do {
+ if ((zone = get_key(*zsk_key, &ttl, &flags, &protocol, &algorithm, (char *)&tmp, sizeof(tmp), &keyid)) == NULL) {
+ dolog(LOG_INFO, "get_key %s\n", (*zsk_key)->keyname);
+ return -1;
+ }
+
+ /* check the keytag supplied */
+ p = key;
+ pack16(p, htons(flags));
+ p += 2;
+ pack8(p, protocol);
+ p++;
+ pack8(p, algorithm);
+ p++;
+ keylen = mybase64_decode(tmp, (char *)&signature, sizeof(signature));
+ pack(p, signature, keylen);
+ p += keylen;
+ keylen = (p - key);
+ if (keyid != keytag(key, keylen)) {
+ dolog(LOG_ERR, "keytag does not match %d vs. %d\n", keyid, keytag(key, keylen));
+ return -1;
+ }
+
+ labels = label_count(rbt->zone);
+ if (labels < 0) {
+ dolog(LOG_INFO, "label_count");
+ return -1;
+ }
+
+ dnsname = dns_label(zonename, &labellen);
+ if (dnsname == NULL)
+ return -1;
+
+ if ((rrset = find_rr(rbt, DNS_TYPE_RP)) != NULL) {
+ rrp = TAILQ_FIRST(&rrset->rr_head);
+ if (rrp == NULL) {
+ dolog(LOG_INFO, "no RP records but have flags!\n");
+ return -1;
+ }
+ } else {
+ dolog(LOG_INFO, "no RP records\n");
+ return -1;
+ }
+
+ p = key;
+
+ pack16(p, htons(DNS_TYPE_RP));
+ p += 2;
+ pack8(p, algorithm);
+ p++;
+ pack8(p, labels);
+ p++;
+ pack32(p, htonl(rrset->ttl));
+ p += 4;
+
+ snprintf(timebuf, sizeof(timebuf), "%lld", expiredon);
+ strptime(timebuf, "%Y%m%d%H%M%S", &tm);
+ expiredon2 = timegm(&tm);
+ snprintf(timebuf, sizeof(timebuf), "%lld", signedon);
+ strptime(timebuf, "%Y%m%d%H%M%S", &tm);
+ signedon2 = timegm(&tm);
+
+ pack32(p, htonl(expiredon2));
+ p += 4;
+ pack32(p, htonl(signedon2));
+ p += 4;
+ pack16(p, htons(keyid));
+ p += 2;
+ pack(p, dnsname, labellen);
+ p += labellen;
+
+ /* no signature here */
+ /* XXX this should probably be done on a canonical sorted records */
+
+ TAILQ_FOREACH(rrp2, &rrset->rr_head, entries) {
+ q = tmpkey;
+ pack(q, rbt->zone, rbt->zonelen);
+ q += rbt->zonelen;
+ pack16(q, htons(DNS_TYPE_RP));
+ q += 2;
+ pack16(q, htons(DNS_CLASS_IN));
+ q += 2;
+ pack32(q, htonl(rrset->ttl));
+ q += 4;
+ pack16(q, htons(((struct rp *)rrp2->rdata)->mboxlen + ((struct rp *)rrp2->rdata)->txtlen));
+ q += 2;
+
+ pack(q, ((struct rp *)rrp2->rdata)->mbox, ((struct rp *)rrp2->rdata)->mboxlen);
+ q += ((struct rp *)rrp2->rdata)->mboxlen;
+
+ pack(q, ((struct rp *)rrp2->rdata)->txt, ((struct rp *)rrp2->rdata)->txtlen);
+ q += ((struct rp *)rrp2->rdata)->txtlen;
+
+
+ c1 = malloc(sizeof(struct canonical));
+ if (c1 == NULL) {
+ dolog(LOG_INFO, "c1 out of memory\n");
+ return -1;
+ }
+
+ c1->len = (q - tmpkey);
+ c1->data = malloc(c1->len);
+ if (c1->data == NULL) {
+ dolog(LOG_INFO, "c1->data out of memory\n");
+ return -1;
+ }
+
+ memcpy(c1->data, tmpkey, c1->len);
+
+ if (TAILQ_EMPTY(&head))
+ TAILQ_INSERT_TAIL(&head, c1, entries);
+ else {
+ TAILQ_FOREACH(c2, &head, entries) {
+ if (c1->len < c2->len)
+ break;
+ else if (c2->len == c1->len &&
+ memcmp(c1->data, c2->data, c1->len) < 0)
+ break;
+ }
+
+ if (c2 != NULL)
+ TAILQ_INSERT_BEFORE(c2, c1, entries);
+ else
+ TAILQ_INSERT_TAIL(&head, c1, entries);
+ }
+ }
+
+ TAILQ_FOREACH_SAFE(c2, &head, entries, cp) {
+ pack(p, c2->data, c2->len);
+ p += c2->len;
+
+ TAILQ_REMOVE(&head, c2, entries);
+ }
+ keylen = (p - key);
+
+#if 0
+ debug_bindump(key, keylen);
+#endif
+ if (sign(algorithm, key, keylen, *zsk_key, (char *)&signature, &siglen) < 0) {
+ dolog(LOG_INFO, "signing failed\n");
+ return -1;
+ }
+
+ len = mybase64_encode(signature, siglen, tmp, sizeof(tmp));
+ tmp[len] = '\0';
+
+ if (fill_rrsig(db, rbt->humanname, "RRSIG", rrset->ttl, "RP", algorithm, labels, rrset->ttl, expiredon, signedon, keyid, zonename, tmp) < 0) {
+ dolog(LOG_INFO, "fill_rrsig\n");
+ return -1;
+ }
+
+ } while ((*++zsk_key) != NULL);
+
+ return 0;
+}
+
+static int
+sign_hinfo(ddDB *db, char *zonename, int expiry, struct rbtree *rbt, int rollmethod)
+{
+ struct rrset *rrset = NULL;
+ struct rr *rrp = NULL;
+ struct rr *rrp2 = NULL;
+ struct keysentry **zsk_key;
+
+ char tmp[4096];
+ char signature[4096];
+ char shabuf[64];
+
+
+ char *dnsname;
+ char *p, *q;
+ char *key, *tmpkey;
+ char *zone;
+
+ uint32_t ttl;
+ uint16_t flags;
+ uint8_t protocol;
+ uint8_t algorithm;
+
+ int labellen;
+ int keyid;
+ int len;
+ int keylen, siglen = sizeof(signature);
+ int labels;
+ int nzk = 0;
+
+ char timebuf[32];
+ struct tm tm;
+ u_int32_t expiredon2, signedon2;
+ TAILQ_HEAD(listhead, canonical) head;
+
+ struct canonical {
+ char *data;
+ int len;
+ TAILQ_ENTRY(canonical) entries;
+ } *c1, *c2, *cp;
+
+
+ TAILQ_INIT(&head);
+ memset(&shabuf, 0, sizeof(shabuf));
+
+ key = malloc(10 * 4096);
+ if (key == NULL) {
+ dolog(LOG_INFO, "key out of memory\n");
+ return -1;
+ }
+ tmpkey = malloc(10 * 4096);
+ if (tmpkey == NULL) {
+ dolog(LOG_INFO, "tmpkey out of memory\n");
+ return -1;
+ }
+
+ zsk_key = calloc(3, sizeof(struct keysentry *));
+ if (zsk_key == NULL) {
+ dolog(LOG_INFO, "out of memory\n");
+ return -1;
+ }
+
+ nzk = 0;
+ SLIST_FOREACH(knp, &keyshead, keys_entry) {
+ if ((knp->type == KEYTYPE_ZSK && rollmethod == \
+ ROLLOVER_METHOD_DOUBLE_SIGNATURE) || \
+ (knp->sign == 1 && knp->type == KEYTYPE_ZSK)) {
+ zsk_key[nzk++] = knp;
+ }
+ }
+
+ zsk_key[nzk] = NULL;
+
+ /* get the ZSK */
+ do {
+ if ((zone = get_key(*zsk_key, &ttl, &flags, &protocol, &algorithm, (char *)&tmp, sizeof(tmp), &keyid)) == NULL) {
+ dolog(LOG_INFO, "get_key %s\n", (*zsk_key)->keyname);
+ return -1;
+ }
+
+ /* check the keytag supplied */
+ p = key;
+ pack16(p, htons(flags));
+ p += 2;
+ pack8(p, protocol);
+ p++;
+ pack8(p, algorithm);
+ p++;
+ keylen = mybase64_decode(tmp, (char *)&signature, sizeof(signature));
+ pack(p, signature, keylen);
+ p += keylen;
+ keylen = (p - key);
+ if (keyid != keytag(key, keylen)) {
+ dolog(LOG_ERR, "keytag does not match %d vs. %d\n", keyid, keytag(key, keylen));
+ return -1;
+ }
+
+ labels = label_count(rbt->zone);
+ if (labels < 0) {
+ dolog(LOG_INFO, "label_count");
+ return -1;
+ }
+
+ dnsname = dns_label(zonename, &labellen);
+ if (dnsname == NULL)
+ return -1;
+
+ if ((rrset = find_rr(rbt, DNS_TYPE_HINFO)) != NULL) {
+ rrp = TAILQ_FIRST(&rrset->rr_head);
+ if (rrp == NULL) {
+ dolog(LOG_INFO, "no HINFO records but have flags!\n");
+ return -1;
+ }
+ } else {
+ dolog(LOG_INFO, "no HINFO records\n");
+ return -1;
+ }
+
+ p = key;
+
+ pack16(p, htons(DNS_TYPE_HINFO));
+ p += 2;
+ pack8(p, algorithm);
+ p++;
+ pack8(p, labels);
+ p++;
+ pack32(p, htonl(rrset->ttl));
+ p += 4;
+
+ snprintf(timebuf, sizeof(timebuf), "%lld", expiredon);
+ strptime(timebuf, "%Y%m%d%H%M%S", &tm);
+ expiredon2 = timegm(&tm);
+ snprintf(timebuf, sizeof(timebuf), "%lld", signedon);
+ strptime(timebuf, "%Y%m%d%H%M%S", &tm);
+ signedon2 = timegm(&tm);
+
+ pack32(p, htonl(expiredon2));
+ p += 4;
+ pack32(p, htonl(signedon2));
+ p += 4;
+ pack16(p, htons(keyid));
+ p += 2;
+ pack(p, dnsname, labellen);
+ p += labellen;
+
+ /* no signature here */
+ /* XXX this should probably be done on a canonical sorted records */
+
+ TAILQ_FOREACH(rrp2, &rrset->rr_head, entries) {
+ q = tmpkey;
+ pack(q, rbt->zone, rbt->zonelen);
+ q += rbt->zonelen;
+ pack16(q, htons(DNS_TYPE_HINFO));
+ q += 2;
+ pack16(q, htons(DNS_CLASS_IN));
+ q += 2;
+ pack32(q, htonl(rrset->ttl));
+ q += 4;
+ pack16(q, htons(2 + ((struct hinfo *)rrp2->rdata)->cpulen + ((struct hinfo *)rrp2->rdata)->oslen));
+ q += 2;
+
+ pack8(q, ((struct hinfo *)rrp2->rdata)->cpulen);
+ q++;
+ pack(q, ((struct hinfo *)rrp2->rdata)->cpu, ((struct hinfo *)rrp2->rdata)->cpulen);
+ q += ((struct hinfo *)rrp2->rdata)->cpulen;
+
+ pack8(q, ((struct hinfo *)rrp2->rdata)->oslen);
+ q++;
+ pack(q, ((struct hinfo *)rrp2->rdata)->os, ((struct hinfo *)rrp2->rdata)->oslen);
+ q += ((struct hinfo *)rrp2->rdata)->oslen;
+
+
+ c1 = malloc(sizeof(struct canonical));
+ if (c1 == NULL) {
+ dolog(LOG_INFO, "c1 out of memory\n");
+ return -1;
+ }
+
+ c1->len = (q - tmpkey);
+ c1->data = malloc(c1->len);
+ if (c1->data == NULL) {
+ dolog(LOG_INFO, "c1->data out of memory\n");
+ return -1;
+ }
+
+ memcpy(c1->data, tmpkey, c1->len);
+
+ if (TAILQ_EMPTY(&head))
+ TAILQ_INSERT_TAIL(&head, c1, entries);
+ else {
+ TAILQ_FOREACH(c2, &head, entries) {
+ if (c1->len < c2->len)
+ break;
+ else if (c2->len == c1->len &&
+ memcmp(c1->data, c2->data, c1->len) < 0)
+ break;
+ }
+
+ if (c2 != NULL)
+ TAILQ_INSERT_BEFORE(c2, c1, entries);
+ else
+ TAILQ_INSERT_TAIL(&head, c1, entries);
+ }
+ }
+
+ TAILQ_FOREACH_SAFE(c2, &head, entries, cp) {
+ pack(p, c2->data, c2->len);
+ p += c2->len;
+
+ TAILQ_REMOVE(&head, c2, entries);
+ }
+ keylen = (p - key);
+
+#if 0
+ debug_bindump(key, keylen);
+#endif
+ if (sign(algorithm, key, keylen, *zsk_key, (char *)&signature, &siglen) < 0) {
+ dolog(LOG_INFO, "signing failed\n");
+ return -1;
+ }
+
+ len = mybase64_encode(signature, siglen, tmp, sizeof(tmp));
+ tmp[len] = '\0';
+
+ if (fill_rrsig(db, rbt->humanname, "RRSIG", rrset->ttl, "HINFO", algorithm, labels, rrset->ttl, expiredon, signedon, keyid, zonename, tmp) < 0) {
+ dolog(LOG_INFO, "fill_rrsig\n");
+ return -1;
+ }
+
+ } while ((*++zsk_key) != NULL);
+
+ return 0;
+}
+
/*
+ * create a RRSIG for an CAA record
+ */
+
+static int
+sign_caa(ddDB *db, char *zonename, int expiry, struct rbtree *rbt, int rollmethod)
+{
+ struct rrset *rrset = NULL;
+ struct rr *rrp = NULL;
+ struct rr *rrp2 = NULL;
+ struct keysentry **zsk_key;
+
+ char tmp[4096];
+ char signature[4096];
+ char shabuf[64];
+
+
+ char *dnsname;
+ char *p, *q;
+ char *key, *tmpkey;
+ char *zone;
+
+ uint32_t ttl;
+ uint16_t flags;
+ uint8_t protocol;
+ uint8_t algorithm;
+
+ int labellen;
+ int keyid;
+ int len;
+ int keylen, siglen = sizeof(signature);
+ int labels;
+ int nzk = 0;
+
+ char timebuf[32];
+ struct tm tm;
+ u_int32_t expiredon2, signedon2;
+ TAILQ_HEAD(listhead, canonical) head;
+
+ struct canonical {
+ char *data;
+ int len;
+ TAILQ_ENTRY(canonical) entries;
+ } *c1, *c2, *cp;
+
+
+ TAILQ_INIT(&head);
+ memset(&shabuf, 0, sizeof(shabuf));
+
+ key = malloc(10 * 4096);
+ if (key == NULL) {
+ dolog(LOG_INFO, "key out of memory\n");
+ return -1;
+ }
+ tmpkey = malloc(10 * 4096);
+ if (tmpkey == NULL) {
+ dolog(LOG_INFO, "tmpkey out of memory\n");
+ return -1;
+ }
+
+ zsk_key = calloc(3, sizeof(struct keysentry *));
+ if (zsk_key == NULL) {
+ dolog(LOG_INFO, "out of memory\n");
+ return -1;
+ }
+
+ nzk = 0;
+ SLIST_FOREACH(knp, &keyshead, keys_entry) {
+ if ((knp->type == KEYTYPE_ZSK && rollmethod == \
+ ROLLOVER_METHOD_DOUBLE_SIGNATURE) || \
+ (knp->sign == 1 && knp->type == KEYTYPE_ZSK)) {
+ zsk_key[nzk++] = knp;
+ }
+ }
+
+ zsk_key[nzk] = NULL;
+
+ /* get the ZSK */
+ do {
+ if ((zone = get_key(*zsk_key, &ttl, &flags, &protocol, &algorithm, (char *)&tmp, sizeof(tmp), &keyid)) == NULL) {
+ dolog(LOG_INFO, "get_key %s\n", (*zsk_key)->keyname);
+ return -1;
+ }
+
+ /* check the keytag supplied */
+ p = key;
+ pack16(p, htons(flags));
+ p += 2;
+ pack8(p, protocol);
+ p++;
+ pack8(p, algorithm);
+ p++;
+ keylen = mybase64_decode(tmp, (char *)&signature, sizeof(signature));
+ pack(p, signature, keylen);
+ p += keylen;
+ keylen = (p - key);
+ if (keyid != keytag(key, keylen)) {
+ dolog(LOG_ERR, "keytag does not match %d vs. %d\n", keyid, keytag(key, keylen));
+ return -1;
+ }
+
+ labels = label_count(rbt->zone);
+ if (labels < 0) {
+ dolog(LOG_INFO, "label_count");
+ return -1;
+ }
+
+ dnsname = dns_label(zonename, &labellen);
+ if (dnsname == NULL)
+ return -1;
+
+ if ((rrset = find_rr(rbt, DNS_TYPE_CAA)) != NULL) {
+ rrp = TAILQ_FIRST(&rrset->rr_head);
+ if (rrp == NULL) {
+ dolog(LOG_INFO, "no CAA records but have flags!\n");
+ return -1;
+ }
+ } else {
+ dolog(LOG_INFO, "no CAA records\n");
+ return -1;
+ }
+
+ p = key;
+
+ pack16(p, htons(DNS_TYPE_CAA));
+ p += 2;
+ pack8(p, algorithm);
+ p++;
+ pack8(p, labels);
+ p++;
+ pack32(p, htonl(rrset->ttl));
+ p += 4;
+
+ snprintf(timebuf, sizeof(timebuf), "%lld", expiredon);
+ strptime(timebuf, "%Y%m%d%H%M%S", &tm);
+ expiredon2 = timegm(&tm);
+ snprintf(timebuf, sizeof(timebuf), "%lld", signedon);
+ strptime(timebuf, "%Y%m%d%H%M%S", &tm);
+ signedon2 = timegm(&tm);
+
+ pack32(p, htonl(expiredon2));
+ p += 4;
+ pack32(p, htonl(signedon2));
+ p += 4;
+ pack16(p, htons(keyid));
+ p += 2;
+ pack(p, dnsname, labellen);
+ p += labellen;
+
+ /* no signature here */
+ /* XXX this should probably be done on a canonical sorted records */
+
+ TAILQ_FOREACH(rrp2, &rrset->rr_head, entries) {
+ q = tmpkey;
+ pack(q, rbt->zone, rbt->zonelen);
+ q += rbt->zonelen;
+ pack16(q, htons(DNS_TYPE_CAA));
+ q += 2;
+ pack16(q, htons(DNS_CLASS_IN));
+ q += 2;
+ pack32(q, htonl(rrset->ttl));
+ q += 4;
+ pack16(q, htons(1 + 1 + ((struct caa *)rrp2->rdata)->taglen + ((struct caa *)rrp2->rdata)->valuelen));
+ q += 2;
+
+ pack8(q, ((struct caa *)rrp2->rdata)->flags);
+ q++;
+ pack8(q, ((struct caa *)rrp2->rdata)->taglen);
+ q++;
+ pack(q, ((struct caa *)rrp2->rdata)->tag, ((struct caa *)rrp2->rdata)->taglen);
+ q += ((struct caa *)rrp2->rdata)->taglen;
+
+ pack(q, ((struct caa *)rrp2->rdata)->value, ((struct caa *)rrp2->rdata)->valuelen);
+ q += ((struct caa *)rrp2->rdata)->valuelen;
+
+
+ c1 = malloc(sizeof(struct canonical));
+ if (c1 == NULL) {
+ dolog(LOG_INFO, "c1 out of memory\n");
+ return -1;
+ }
+
+ c1->len = (q - tmpkey);
+ c1->data = malloc(c1->len);
+ if (c1->data == NULL) {
+ dolog(LOG_INFO, "c1->data out of memory\n");
+ return -1;
+ }
+
+ memcpy(c1->data, tmpkey, c1->len);
+
+ if (TAILQ_EMPTY(&head))
+ TAILQ_INSERT_TAIL(&head, c1, entries);
+ else {
+ TAILQ_FOREACH(c2, &head, entries) {
+ if (c1->len < c2->len)
+ break;
+ else if (c2->len == c1->len &&
+ memcmp(c1->data, c2->data, c1->len) < 0)
+ break;
+ }
+
+ if (c2 != NULL)
+ TAILQ_INSERT_BEFORE(c2, c1, entries);
+ else
+ TAILQ_INSERT_TAIL(&head, c1, entries);
+ }
+ }
+
+ TAILQ_FOREACH_SAFE(c2, &head, entries, cp) {
+ pack(p, c2->data, c2->len);
+ p += c2->len;
+
+ TAILQ_REMOVE(&head, c2, entries);
+ }
+ keylen = (p - key);
+
+#if 0
+ debug_bindump(key, keylen);
+#endif
+ if (sign(algorithm, key, keylen, *zsk_key, (char *)&signature, &siglen) < 0) {
+ dolog(LOG_INFO, "signing failed\n");
+ return -1;
+ }
+
+ len = mybase64_encode(signature, siglen, tmp, sizeof(tmp));
+ tmp[len] = '\0';
+
+ if (fill_rrsig(db, rbt->humanname, "RRSIG", rrset->ttl, "CAA", algorithm, labels, rrset->ttl, expiredon, signedon, keyid, zonename, tmp) < 0) {
+ dolog(LOG_INFO, "fill_rrsig\n");
+ return -1;
+ }
+
+ } while ((*++zsk_key) != NULL);
+
+ return 0;
+}
+
+/*
* create a RRSIG for an DS record
*/
@@ -6065,6 +6787,12 @@ construct_nsec3(ddDB *db, char *zone, int iterations,
strlcat(bitmap, "DS ", sizeof(bitmap));
if (find_rr(rbt, DNS_TYPE_SSHFP) != NULL)
strlcat(bitmap, "SSHFP ", sizeof(bitmap));
+ if (find_rr(rbt, DNS_TYPE_RP) != NULL)
+ strlcat(bitmap, "RP ", sizeof(bitmap));
+ if (find_rr(rbt, DNS_TYPE_HINFO) != NULL)
+ strlcat(bitmap, "HINFO ", sizeof(bitmap));
+ if (find_rr(rbt, DNS_TYPE_CAA) != NULL)
+ strlcat(bitmap, "CAA ", sizeof(bitmap));
/* they all have RRSIG */
strlcat(bitmap, "RRSIG ", sizeof(bitmap));
@@ -6395,9 +7123,63 @@ print_rbt(FILE *of, struct rbtree *rbt)
buf);
}
}
+ if ((rrset = find_rr(rbt, DNS_TYPE_RP)) != NULL) {
+ if ((rrp = TAILQ_FIRST(&rrset->rr_head)) == NULL) {
+ dolog(LOG_INFO, "no hinfo in zone!\n");
+ return -1;
+ }
+ TAILQ_FOREACH(rrp2, &rrset->rr_head, entries) {
+ fprintf(of, " %s,rp,%d,%s,%s\n",
+ convert_name(rbt->zone, rbt->zonelen),
+ rrset->ttl,
+ convert_name(((struct rp *)rrp2->rdata)->mbox, ((struct rp *)rrp2->rdata)->mboxlen),
+ convert_name(((struct rp *)rrp2->rdata)->txt, ((struct rp *)rrp2->rdata)->txtlen));
+ }
+ }
+ if ((rrset = find_rr(rbt, DNS_TYPE_CAA)) != NULL) {
+ if ((rrp = TAILQ_FIRST(&rrset->rr_head)) == NULL) {
+ dolog(LOG_INFO, "no hinfo in zone!\n");
+ return -1;
+ }
+ TAILQ_FOREACH(rrp2, &rrset->rr_head, entries) {
+ fprintf(of, " %s,caa,%d,%d,",
+ convert_name(rbt->zone, rbt->zonelen),
+ rrset->ttl,
+ ((struct caa *)rrp2->rdata)->flags);
+
+ for (i = 0; i < ((struct caa *)rrp2->rdata)->taglen; i++) {
+ fprintf(of, "%c", ((struct caa *)rrp2->rdata)->tag[i]);
+ }
+ fprintf(of, ",\"");
+ for (i = 0; i < ((struct caa *)rrp2->rdata)->valuelen; i++) {
+ fprintf(of, "%c", ((struct caa *)rrp2->rdata)->value[i]);
+ }
+ fprintf(of, "\"\n");
+ }
+ }
+ if ((rrset = find_rr(rbt, DNS_TYPE_HINFO)) != NULL) {
+ if ((rrp = TAILQ_FIRST(&rrset->rr_head)) == NULL) {
+ dolog(LOG_INFO, "no hinfo in zone!\n");
+ return -1;
+ }
+ TAILQ_FOREACH(rrp2, &rrset->rr_head, entries) {
+ fprintf(of, " %s,hinfo,%d,\"",
+ convert_name(rbt->zone, rbt->zonelen),
+ rrset->ttl);
+
+ for (i = 0; i < ((struct hinfo *)rrp2->rdata)->cpulen; i++) {
+ fprintf(of, "%c", ((struct hinfo *)rrp2->rdata)->cpu[i]);
+ }
+ fprintf(of, "\",\"");
+ for (i = 0; i < ((struct hinfo *)rrp2->rdata)->oslen; i++) {
+ fprintf(of, "%c", ((struct hinfo *)rrp2->rdata)->os[i]);
+ }
+ fprintf(of, "\"\n");
+ }
+ }
if ((rrset = find_rr(rbt, DNS_TYPE_AAAA)) != NULL) {
if ((rrp = TAILQ_FIRST(&rrset->rr_head)) == NULL) {
- dolog(LOG_INFO, "no naptr in zone!\n");
+ dolog(LOG_INFO, "no aaaa in zone!\n");
return -1;
}
TAILQ_FOREACH(rrp2, &rrset->rr_head, entries) {
blob - f5311b6585d81f375d07d2f496cde5521faf94d1
blob + 8324fbf141bb7cf23966b06757bd20f5973108f9
--- util.c
+++ util.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: util.c,v 1.76 2020/07/21 18:19:58 pjp Exp $
+ * $Id: util.c,v 1.77 2020/07/23 10:48:45 pjp Exp $
*/
#include <sys/types.h>
@@ -158,6 +158,9 @@ extern int raxfr_rrsig(FILE *, u_char *, u_char *, u_c
extern int raxfr_nsec3param(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
extern int raxfr_nsec3(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
extern int raxfr_ds(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
+extern int raxfr_rp(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
+extern int raxfr_caa(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
+extern int raxfr_hinfo(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
extern int raxfr_sshfp(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
extern u_int16_t raxfr_skip(FILE *, u_char *, u_char *);
extern int raxfr_soa(FILE *, u_char *, u_char *, u_char *, struct soa *, int, u_int32_t, u_int16_t, HMAC_CTX *);
@@ -190,16 +193,21 @@ struct typetable {
{ "NSEC3", DNS_TYPE_NSEC3 },
{ "NSEC3PARAM", DNS_TYPE_NSEC3PARAM },
{ "TLSA", DNS_TYPE_TLSA },
+ { "RP", DNS_TYPE_RP },
+ { "HINFO", DNS_TYPE_HINFO },
+ { "CAA", DNS_TYPE_CAA },
{ NULL, 0}
};
static struct rrtab myrrtab[] = {
{ "a", DNS_TYPE_A, DNS_TYPE_A } ,
{ "aaaa", DNS_TYPE_AAAA, DNS_TYPE_AAAA },
+ { "caa", DNS_TYPE_CAA, DNS_TYPE_CAA },
{ "cname", DNS_TYPE_CNAME, DNS_TYPE_CNAME },
{ "delegate", DNS_TYPE_NS, DNS_TYPE_NS },
{ "dnskey", DNS_TYPE_DNSKEY, DNS_TYPE_DNSKEY },
{ "ds", DNS_TYPE_DS, DNS_TYPE_DS },
+ { "hinfo", DNS_TYPE_HINFO, DNS_TYPE_HINFO },
{ "hint", DNS_TYPE_HINT, DNS_TYPE_NS },
{ "mx", DNS_TYPE_MX, DNS_TYPE_MX },
{ "naptr", DNS_TYPE_NAPTR, DNS_TYPE_NAPTR },
@@ -208,6 +216,7 @@ static struct rrtab myrrtab[] = {
{ "nsec3", DNS_TYPE_NSEC3, DNS_TYPE_NSEC3 },
{ "nsec3param", DNS_TYPE_NSEC3PARAM, DNS_TYPE_NSEC3PARAM },
{ "ptr", DNS_TYPE_PTR, DNS_TYPE_PTR },
+ { "rp", DNS_TYPE_RP, DNS_TYPE_RP },
{ "rrsig", DNS_TYPE_RRSIG, DNS_TYPE_RRSIG },
{ "soa", DNS_TYPE_SOA, DNS_TYPE_SOA },
{ "srv", DNS_TYPE_SRV, DNS_TYPE_SRV },
@@ -235,6 +244,9 @@ static struct raxfr_logic supported[] = {
{ DNS_TYPE_TLSA, 0, raxfr_tlsa },
{ DNS_TYPE_SRV, 0, raxfr_srv },
{ DNS_TYPE_NAPTR, 0, raxfr_naptr },
+ { DNS_TYPE_RP, 0, raxfr_rp },
+ { DNS_TYPE_HINFO, 0, raxfr_hinfo },
+ { DNS_TYPE_CAA, 0, raxfr_caa },
{ 0, 0, NULL }
};
@@ -679,6 +691,33 @@ check_qtype(struct rbtree *rbt, u_int16_t type, int nx
*error = -1;
return 0;
+ case DNS_TYPE_CAA:
+ if (find_rr(rbt, DNS_TYPE_CAA) != NULL) {
+ returnval = DNS_TYPE_CAA;
+ break;
+ }
+
+ *error = -1;
+ return 0;
+
+ case DNS_TYPE_RP:
+ if (find_rr(rbt, DNS_TYPE_RP) != NULL) {
+ returnval = DNS_TYPE_RP;
+ break;
+ }
+
+ *error = -1;
+ return 0;
+
+ case DNS_TYPE_HINFO:
+ if (find_rr(rbt, DNS_TYPE_HINFO) != NULL) {
+ returnval = DNS_TYPE_HINFO;
+ break;
+ }
+
+ *error = -1;
+ return 0;
+
case DNS_TYPE_SSHFP:
if (find_rr(rbt, DNS_TYPE_SSHFP) != NULL) {
returnval = DNS_TYPE_SSHFP;
@@ -1727,49 +1766,49 @@ bitmap2human(char *bitmap, int len)
for (j = 0; j < 32; j++) {
if (expanded_bitmap[j] & 0x80) {
x = 0;
- bit = (block * 255) + ((j * 8) + x);
+ bit = (block * 256) + ((j * 8) + x);
strlcat(human, get_dns_type(bit, 0), sizeof(human));
strlcat(human, " ", sizeof(human));
}
if (expanded_bitmap[j] & 0x40) {
x = 1;
- bit = (block * 255) + ((j * 8) + x);
+ bit = (block * 256) + ((j * 8) + x);
strlcat(human, get_dns_type(bit, 0), sizeof(human));
strlcat(human, " ", sizeof(human));
}
if (expanded_bitmap[j] & 0x20) {
x = 2;
- bit = (block * 255) + ((j * 8) + x);
+ bit = (block * 256) + ((j * 8) + x);
strlcat(human, get_dns_type(bit, 0), sizeof(human));
strlcat(human, " ", sizeof(human));
}
if (expanded_bitmap[j] & 0x10) {
x = 3;
- bit = (block * 255) + ((j * 8) + x);
+ bit = (block * 256) + ((j * 8) + x);
strlcat(human, get_dns_type(bit, 0), sizeof(human));
strlcat(human, " ", sizeof(human));
}
if (expanded_bitmap[j] & 0x8) {
x = 4;
- bit = (block * 255) + ((j * 8) + x);
+ bit = (block * 256) + ((j * 8) + x);
strlcat(human, get_dns_type(bit, 0), sizeof(human));
strlcat(human, " ", sizeof(human));
}
if (expanded_bitmap[j] & 0x4) {
x = 5;
- bit = (block * 255) + ((j * 8) + x);
+ bit = (block * 256) + ((j * 8) + x);
strlcat(human, get_dns_type(bit, 0), sizeof(human));
strlcat(human, " ", sizeof(human));
}
if (expanded_bitmap[j] & 0x2) {
x = 6;
- bit = (block * 255) + ((j * 8) + x);
+ bit = (block * 256) + ((j * 8) + x);
strlcat(human, get_dns_type(bit, 0), sizeof(human));
strlcat(human, " ", sizeof(human));
}
if (expanded_bitmap[j] & 0x1) {
x = 7;
- bit = (block * 255) + ((j * 8) + x);
+ bit = (block * 256) + ((j * 8) + x);
strlcat(human, get_dns_type(bit, 0), sizeof(human));
strlcat(human, " ", sizeof(human));
}
repomaster@centroid.eu