summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile14
-rw-r--r--dns.c41
-rw-r--r--dns.h3
-rw-r--r--dnstlsa.c99
4 files changed, 156 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 595f47b..fa5c282 100644
--- a/Makefile
+++ b/Makefile
@@ -479,6 +479,18 @@ compile dnsptr.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
479str.h scan.h dns.h dnsdoe.h ip.h exit.h 479str.h scan.h dns.h dnsdoe.h ip.h exit.h
480 ./compile dnsptr.c 480 ./compile dnsptr.c
481 481
482dnstlsa: \
483load dnstlsa.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
484substdio.a error.a str.a fs.a dns.lib socket.lib
485 ./load dnstlsa dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
486 alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \
487 socket.lib` getopt.a
488
489dnstlsa.o: \
490compile dnstlsa.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
491str.h scan.h dns.h dnsdoe.h ip.h exit.h
492 ./compile dnstlsa.c
493
482dot-qmail.0: \ 494dot-qmail.0: \
483dot-qmail.5 495dot-qmail.5
484 nroff -man dot-qmail.5 > dot-qmail.0 496 nroff -man dot-qmail.5 > dot-qmail.0
@@ -812,7 +824,7 @@ predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \
812qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \ 824qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \
813qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \ 825qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \
814qmail-smtpd sendmail tcp-env qmail-newmrh qmail-newbrt config config-fast dnscname \ 826qmail-smtpd sendmail tcp-env qmail-newmrh qmail-newbrt config config-fast dnscname \
815dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \ 827dnsptr dnsip dnsmxip dnsfq dnstlsa hostname ipmeprint qreceipt qsmhook qbiff \
816forward preline condredirect bouncesaying except maildirmake \ 828forward preline condredirect bouncesaying except maildirmake \
817maildir2mbox maildirwatch qail elq pinq idedit install-big install \ 829maildir2mbox maildirwatch qail elq pinq idedit install-big install \
818instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \ 830instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
diff --git a/dns.c b/dns.c
index bed2bd2..b4d106c 100644
--- a/dns.c
+++ b/dns.c
@@ -418,3 +418,44 @@ unsigned long random;
418 alloc_free(mx); 418 alloc_free(mx);
419 return flagsoft; 419 return flagsoft;
420} 420}
421
422int dns_tlsa(stralloc *out, const stralloc *fqdn)
423{
424 int ranswers = 0;
425
426 switch(resolve(fqdn, T_TLSA))
427 {
428 case DNS_MEM: return DNS_MEM;
429 case DNS_SOFT: return DNS_SOFT;
430 case DNS_HARD: return DNS_HARD;
431 }
432
433 if (!stralloc_copys(out,"")) return DNS_MEM;
434 while(numanswers-- > 0) {
435 int i;
436 if (responsepos == responseend) return DNS_SOFT;
437
438 i = dn_expand(response.buf, responseend, responsepos, name, MAXDNAME);
439 if (i < 0) return DNS_SOFT;
440 responsepos += i;
441
442 i = responseend - responsepos;
443 if (i < 4 + 3 * 2) return DNS_SOFT;
444
445 unsigned short rrtype = getshort(responsepos);
446 unsigned short rrdlen = getshort(responsepos + 8);
447 responsepos += 10; // skip dns header
448 if (responsepos + rrdlen > responseend) return DNS_HARD;
449
450 if (rrtype == T_TLSA)
451 {
452 unsigned char rrlen[2] = { rrdlen >> 8, rrdlen & 0xFF };
453 stralloc_catb(out, rrlen, 2);
454 if (!stralloc_catb(out, responsepos, rrdlen)) return DNS_MEM;
455 ++ranswers;
456 }
457
458 responsepos += rrdlen;
459 }
460 return ranswers;
461}
diff --git a/dns.h b/dns.h
index bca9490..08534a2 100644
--- a/dns.h
+++ b/dns.h
@@ -1,6 +1,8 @@
1#ifndef DNS_H 1#ifndef DNS_H
2#define DNS_H 2#define DNS_H
3 3
4#include "stralloc.h"
5
4#define DNS_SOFT -1 6#define DNS_SOFT -1
5#define DNS_HARD -2 7#define DNS_HARD -2
6#define DNS_MEM -3 8#define DNS_MEM -3
@@ -10,5 +12,6 @@ int dns_cname();
10int dns_mxip(); 12int dns_mxip();
11int dns_ip(); 13int dns_ip();
12int dns_ptr(); 14int dns_ptr();
15int dns_tlsa(stralloc *out, const stralloc *fqdn);
13 16
14#endif 17#endif
diff --git a/dnstlsa.c b/dnstlsa.c
new file mode 100644
index 0000000..6623cfd
--- /dev/null
+++ b/dnstlsa.c
@@ -0,0 +1,99 @@
1#include <stdint.h>
2#include "byte.h"
3#include "substdio.h"
4#include "subfd.h"
5#include "subgetopt.h"
6#include "stralloc.h"
7#include "dns.h"
8#include "dnsdoe.h"
9#include "exit.h"
10
11stralloc sa = {0};
12stralloc out = {0};
13
14static void die_nomem()
15{
16 substdio_putsflush(subfderr, "out of memory\n");
17 _exit(111);
18}
19
20 #include <stdio.h>
21void main(int argc, char **argv)
22{
23 char *port = "25";
24 char proto[7] = "._tcp.";
25 char *host = NULL;
26 int opt;
27 int verbose = 0;
28
29 while ((opt = sgopt(argc, argv, "vutp:")) != sgoptdone)
30 {
31 switch(opt)
32 {
33 case 'p': port = sgoptarg; break;
34 case 't': break;
35 case 'u': byte_copy(proto, 6, "._udp."); break;
36 case 'v': verbose = 1;
37 }
38 }
39
40 argv += sgoptind;
41 argc -= sgoptind;
42
43 if (!argv[0])
44 {
45 substdio_putsflush(subfderr, "dnstlsa [-v] [-p port] [-u(dp)|-t(cp)] host (tcp on port 25 is default)\n");
46 _exit(100);
47 }
48 host = argv[0];
49
50 if (!stralloc_copyb(&sa, "_", 1)) die_nomem;
51 if (!stralloc_cats(&sa, port)) die_nomem;
52 if (!stralloc_cats(&sa, proto)) die_nomem;
53 if (!stralloc_cats(&sa, host)) die_nomem;
54
55 if (verbose)
56 {
57 substdio_puts(subfdout, "checking for TLSA records: ");
58 substdio_put(subfdout, sa.s, sa.len);
59 substdio_putsflush(subfdout, "\n");
60 }
61
62 dns_init(0);
63 dnsdoe(dns_tlsa(&out, &sa));
64
65 int pos = 0;
66 unsigned char *response = (unsigned char *)out.s;
67 while(pos < out.len && out.len - pos > 2 + 4) // sizeof(rrlen) + min(rrdata)
68 {
69 unsigned short rrlen = (response[pos] << 8) + response[pos + 1];
70 pos += 2;
71 uint8_t usage = response[pos];
72 uint8_t sel = response[pos + 1];
73 uint8_t type = response[pos + 2];
74
75 if (usage == 0) substdio_puts(subfdout, "usage=0 ");
76 if (usage == 1) substdio_puts(subfdout, "usage=1 ");
77 if (usage == 2) substdio_puts(subfdout, "usage=2 ");
78 if (usage == 3) substdio_puts(subfdout, "usage=3 ");
79
80 if (sel == 0) substdio_puts(subfdout, "selector=0 ");
81 if (sel == 1) substdio_puts(subfdout, "selector=1 ");
82
83 if (type == 0) substdio_puts(subfdout, "type=0 "); // full cert
84 if (type == 1) substdio_puts(subfdout, "type=1 "); // sha256
85 if (type == 2) substdio_puts(subfdout, "type=2 "); // sha512
86
87 substdio_puts(subfdout, "data="); // sha512
88 for (int j = 3; j < rrlen; j++)
89 {
90 unsigned char ch = response[pos + j];
91 substdio_put(subfdout, "0123456789abcdef" + (ch >> 4), 1);
92 substdio_put(subfdout, "0123456789abcdef" + (ch & 0x0F), 1);
93 }
94 substdio_putsflush(subfdout, "\n");
95 pos += rrlen;
96 }
97
98 _exit(0);
99}