summaryrefslogtreecommitdiffstats
path: root/dnstlsa.c
blob: fdb445e1f4d9af4e1722cb4dadf38aa4d7bc4e58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <stdint.h>
#include "byte.h"
#include "substdio.h"
#include "subfd.h"
#include "subgetopt.h"
#include "stralloc.h"
#include "dns.h"
#include "dnsdoe.h"
#include "exit.h"

stralloc sa = {0};
stralloc out = {0};

static void die_nomem()
{
  substdio_putsflush(subfderr, "out of memory\n");
  _exit(111);
}

void main(int argc, char **argv)
{
  char *port = "25";
  char proto[7] = "._tcp.";
  char *host = NULL;
  int opt;
  int verbose = 0;

  while ((opt = sgopt(argc, argv, "vutp:")) != sgoptdone)
  {
    switch(opt)
    {
      case 'p': port = sgoptarg; break;
      case 't': break;
      case 'u': byte_copy(proto, 6, "._udp."); break;
      case 'v': verbose = 1;
    }
  }

  argv += sgoptind;
  argc -= sgoptind;

  if (!argv[0])
  {
    substdio_putsflush(subfderr, "dnstlsa [-v] [-p port] [-u(dp)|-t(cp)] host (tcp on port 25 is default)\n");
    _exit(100);
  }
  host = argv[0];

  if (!stralloc_copyb(&sa, "_", 1)) die_nomem;
  if (!stralloc_cats(&sa, port)) die_nomem;
  if (!stralloc_cats(&sa, proto)) die_nomem;
  if (!stralloc_cats(&sa, host)) die_nomem;

  if (verbose)
  {
    substdio_puts(subfdout, "checking for TLSA records: ");
    substdio_put(subfdout, sa.s, sa.len);
    substdio_putsflush(subfdout, "\n");
  }

  dns_init(0);
  dnsdoe(dns_tlsa(&out, &sa));

  int pos = 0;
  unsigned char *response = (unsigned char *)out.s;
  while(pos < out.len && out.len - pos > 2 + 4) // sizeof(rrlen) + min(rrdata)
  {
    unsigned short rrlen = (response[pos] << 8) + response[pos + 1];
    pos += 2;
    uint8_t usage = response[pos];
    uint8_t sel   = response[pos + 1];
    uint8_t type  = response[pos + 2];

    if (usage == 0) substdio_puts(subfdout, "usage=0 ");
    if (usage == 1) substdio_puts(subfdout, "usage=1 ");
    if (usage == 2) substdio_puts(subfdout, "usage=2 ");
    if (usage == 3) substdio_puts(subfdout, "usage=3 ");

    if (sel == 0) substdio_puts(subfdout, "selector=0 ");
    if (sel == 1) substdio_puts(subfdout, "selector=1 ");

    if (type == 0) substdio_puts(subfdout, "type=0 "); // full cert
    if (type == 1) substdio_puts(subfdout, "type=1 "); // sha256
    if (type == 2) substdio_puts(subfdout, "type=2 "); // sha512

    substdio_puts(subfdout, "data=");
    for (int j = 3; j < rrlen; j++)
    {
      unsigned char ch = response[pos + j];
      substdio_put(subfdout, "0123456789abcdef" + (ch >> 4), 1);
      substdio_put(subfdout, "0123456789abcdef" + (ch & 0x0F), 1);
    }
    substdio_putsflush(subfdout, "\n");
    pos += rrlen;
  }

  _exit(0);
}