Lots of fixes and different setup

This commit is contained in:
Miek Gieben 2012-01-28 12:05:25 +01:00
parent c61fe58508
commit 9c178a49c3
5 changed files with 27 additions and 655 deletions

View File

@ -3,6 +3,6 @@
# license that can be found in the LICENSE file.
include $(GOROOT)/src/Make.inc
TARG=fp
GOFILES=q.go fp.go lex.go dns.go
GOFILES=q.go fp.go
DEPS=../../
include $(GOROOT)/src/Make.cmd

View File

@ -1,292 +0,0 @@
package main
import (
"dns"
)
const (
QUERY_NOERROR string = "QUERY,NOERROR,qr,aa,tc,rd,ra,ad,cd,z,0,0,0,0,do,0,nsid"
QUERY_NOTIFY string = "NOTIFY,NOERROR,qr,AA,tc,RD,ra,ad,cd,Z,0,0,0,0,do,0,nsid"
QUERY_ALL string = "QUERY,NOERROR,QR,AA,TC,RD,RA,AD,CD,Z,0,0,0,0,DO,0,nsid"
)
// Check if the server responds at all
func dnsAlive(l *lexer) stateFn {
l.verbose("Alive")
l.setString(".,IN,NS," + QUERY_NOERROR)
f := l.probe()
if f.ok() {
return dnsServer
}
l.emit(&item{itemError, f.error()})
return nil
}
// This is the starting test. Perform a bunch of queries, get the
// fingerprint a go into a general direction. NsdLike, BindLike, WindowsLike, MaraLike
func dnsServer(l *lexer) stateFn {
l.verbose("Server")
// Set the DO bit
l.setString(".,CH,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,0,0,0,0,DO,4097,NSID")
f := l.probe()
switch {
case !f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeSuccess:
// NSD clears DO bit, but sets UDPSize to 4096. NOERROR.
l.emit(&item{itemVendor, NLNETLABS})
return dnsNsdLike
case !f.Do && f.UDPSize == 0 && f.Rcode == dns.RcodeRefused:
// MaraDNS clears DO BIT, UDPSize to 0. REFUSED
l.emit(&item{itemVendor, MARA})
return dnsMaraLike
case f.Do && f.UDPSize == 2800 && f.Rcode == dns.RcodeSuccess:
// PowerDNS(SEC) set UDP bufsize to 2800, resets UDPSize. NOERROR
fallthrough
case !f.Do && f.UDPSize == 0 && f.Rcode == dns.RcodeSuccess:
// PowerDNS(SEC) clears DO bit, resets UDPSize. NOERROR
l.emit(&item{itemVendor, POWER})
return dnsPowerdnsLike
case !f.Do && f.UDPSize == 0 && f.Rcode == dns.RcodeServerFailure:
// Neustar
l.emit(&item{itemVendor, NEUSTAR})
return dnsNeustarLike
case !f.Do && f.UDPSize == 0 && f.Rcode == dns.RcodeNotImplemented:
// Altas?
l.emit(&item{itemVendor, VERISIGN})
return dnsAtlasLike
case !f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeServerFailure:
// BIND8
fallthrough
case f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeServerFailure:
// BIND9 OLD
fallthrough
case f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeRefused:
// BIND9 leaves DO bit, but sets UDPSize to 4096. REFUSED.
l.emit(&item{itemVendor, ISC})
return dnsBindLike
case f.Do && f.UDPSize == 4097 && f.Rcode == dns.RcodeFormatError:
// Microsoft leaves DO bit, but echo's the UDPSize. FORMERR.
l.emit(&item{itemVendor, MICROSOFT})
return dnsWindowsLike
default:
return nil
}
panic("not reached")
return nil
}
func dnsNsdLike(l *lexer) stateFn {
l.verbose("NsdLike")
l.setString("auThoRs.bInD.,CH,TXT," + QUERY_NOERROR)
l.probe()
return nil
}
func dnsBindLike(l *lexer) stateFn {
l.verbose("BindLike")
l.emit(&item{itemSoftware, BIND})
// Repeat the query, as we get a lot of information from it
l.setString(".,CH,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,0,0,0,0,DO,4097,nsid")
f := l.probe()
switch {
case !f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeServerFailure:
l.emit(&item{itemVersionMajor, "8"})
case f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeServerFailure:
l.emit(&item{itemVersionMajor, "9"})
l.emit(&item{itemVersionMinor, "3"})
case f.Do && f.UDPSize == 4096 && f.Rcode == dns.RcodeRefused:
// BIND9 leaves DO bit, but sets UDPSize to 4096. REFUSED.
l.emit(&item{itemVersionMajor, "9"})
l.emit(&item{itemVersionMinor, "[7..]"})
}
// Try authors.bind
l.setString("auThoRs.bInD.,CH,TXT," + QUERY_NOERROR)
f = l.probe()
switch f.Rcode {
case dns.RcodeServerFailure:
// No authors.bind < 9
l.emit(&item{itemVersionMajor, "8"})
case dns.RcodeSuccess, dns.RcodeRefused:
// BIND 9 or BIND 10
l.emit(&item{itemVersionMajor, "[9..10]"})
}
// The three BIND (8, 9 and 10) behave differently when
// receiving a notify query
l.setString("bind.,NONE,SOA," + QUERY_NOTIFY)
f = l.probe()
switch {
case f.Opcode == dns.OpcodeNotify:
if f.Rcode == dns.RcodeRefused {
l.emit(&item{itemVersionMajor, "9"})
}
if f.Rcode == dns.RcodeServerFailure {
l.emit(&item{itemVersionMajor, "8"})
}
case f.Opcode == dns.OpcodeQuery && f.Rcode == dns.RcodeSuccess:
l.emit(&item{itemVersionMajor, "10"})
if !f.Response {
// Cardinal sin
l.emit(&item{itemVersionMinor, "-devel"})
l.emit(&item{itemVersionPatch, "20110809"})
}
}
return nil
}
func dnsWindowsLike(l *lexer) stateFn {
l.verbose("WindowsLike")
return nil
}
func dnsMaraLike(l *lexer) stateFn {
l.verbose("MaraLike")
return nil
}
func dnsPowerdnsLike(l *lexer) stateFn {
l.verbose("PowerdnsLike")
l.setString(".,CH,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,0,0,0,0,DO,4097,NSID")
f := l.probe()
if !f.Response && f.Query.Qclass == 0 && f.Query.Qtype == 0 && f.Rcode == dns.RcodeSuccess {
// Yadifa does not set the QR bit on this
l.emit(&item{itemVendor, EURID})
return dnsYadifaLike
}
return nil
}
func dnsYadifaLike(l *lexer) stateFn {
l.verbose("YadifaLike")
l.setString(".,CLASS0,TYPE0,QUERY,NOERROR,QR,aa,tc,rd,ra,ad,cd,z,0,0,0,0,do,0,nsid")
l.probe()
l.setString(".,CLASS42,TXT,QUERY,NOERROR,qr,aa,tc,rd,ra,ad,cd,z,0,0,0,0,do,0,nsid")
l.probe()
return nil
}
func dnsNeustarLike(l *lexer) stateFn {
l.verbose("NeustarLike")
return nil
}
func dnsAtlasLike(l *lexer) stateFn {
l.verbose("AtlasLike")
l.setString("MieK.NL.,IN,TXT," + QUERY_NOERROR)
l.probe()
return nil
}
// Check if the server returns the DO-bit when set in the request.
func dnsDoBitMirror(l *lexer) stateFn {
l.verbose("DoBitMirror")
l.setString(".,IN,NS,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,0,0,0,0,DO,0,NSID")
f := l.probe()
// NSD doesn't set the DO bit, but does set the UDPMsg size to 4096.
if !f.Do && f.UDPSize == 4096 {
l.emit(&item{itemSoftware, NSD})
return dnsEDNS0Mangler
}
return dnsEDNS0Mangler
}
func dnsEDNS0Mangler(l *lexer) stateFn {
l.verbose("EDNS0Mangler")
l.setString("NOTIFY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,0,0,0,0,do,0,nsid")
// l.setQuestion("012345678901234567890123456789012345678901234567890123456789012.012345678901234567890123456789012345678901234567890123456789012.012345678901234567890123456789012345678901234567890123456789012.0123456789012345678901234567890123456789012345678901234567890.", dns.TypeA, dns.ClassINET)
f := l.probe()
// MaraDNS does not set the QR bit in the reply... but only with this question is seems
// QUERY,NOERROR,qr,aa,t
if !f.Response && f.Opcode == dns.OpcodeQuery && f.Rcode == dns.RcodeSuccess {
l.emit(&item{itemSoftware, MARADNS})
}
return dnsTcEnable
}
func dnsTcEnable(l *lexer) stateFn {
l.verbose("TcEnable")
l.setString(".,IN,NS,QUERY,NOERROR,qr,aa,TC,rd,ra,ad,cd,z,0,0,0,0,do,0,nsid")
l.probe()
return nil
}
/*
func dnsUDPSize(l *lexer) stateFn {
l.verbose("UDPSize")
l.setString("QUERY,NOERROR,qr,aa,tc,rd,ra,ad,cd,z,0,0,0,0,DO,4097,nsid")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
l.probe()
return dnsZero
}
func dnsZero(l *lexer) stateFn {
l.verbose("Zero")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
l.setString("QUERY,NOERROR,qr,aa,tc,rd,ra,ad,cd,Z,0,0,0,0,do,0,nsid")
l.probe()
return dnsAll
}
func dnsAll(l *lexer) stateFn {
l.verbose("All")
l.setString("QUERY,NOERROR,qr,AA,TC,RD,RA,AD,CD,Z,0,0,0,0,DO,8192,nsid")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
l.probe()
return dnsIquery
}
func dnsIquery(l *lexer) stateFn {
l.verbose("Iquery")
l.setString("IQUERY,NOERROR,qr,aa,tc,rd,ra,ad,cd,Z,0,0,0,0,do,0,nsid")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
l.probe()
return dnsUpdate
}
func dnsUpdate(l *lexer) stateFn {
l.verbose("Update")
l.setString("UPDATE,NOERROR,qr,aa,tc,rd,ra,ad,cd,Z,0,0,0,0,do,0,nsid")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
l.probe()
return dnsStatus
}
func dnsStatus(l *lexer) stateFn {
l.verbose("Status")
l.setString("STATUS,NOERROR,qr,aa,tc,rd,ra,ad,cd,Z,0,0,0,0,do,0,nsid")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
l.probe()
return dnsOpcodeWhacky
}
func dnsOpcodeWhacky(l *lexer) stateFn {
l.verbose("OpcodeWhacky")
l.setString("12,NOERROR,qr,aa,tc,rd,ra,ad,cd,Z,0,0,0,0,do,0,nsid")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
l.probe()
return dnsRcodeWhacky
}
func dnsRcodeWhacky(l *lexer) stateFn {
l.verbose("RcodeWhacky")
l.setString("QUERY,31,qr,aa,tc,rd,ra,ad,cd,Z,0,0,0,0,do,0,nsid")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
l.probe()
return dnsRcodeNotZone
}
func dnsRcodeNotZone(l *lexer) stateFn {
l.verbose("RcodeNotZone")
l.setString("QUERY,NOTZONE,qr,aa,tc,rd,ra,ad,cd,z,0,0,0,0,do,0,nsid")
l.setQuestion(".", dns.TypeNS, dns.ClassINET)
l.probe()
return nil
}
*/

View File

@ -3,7 +3,6 @@ package main
import (
"dns"
"fmt"
"strconv"
"strings"
)
@ -32,37 +31,15 @@ const (
EURID = "EurID"
)
func startParse(addr string) {
l := &lexer{
addr: addr,
client: dns.NewClient(),
fp: new(fingerprint),
items: make(chan item),
state: dnsAlive,
debug: true,
}
l.run()
// Not completely sure about this code..
for {
item := <-l.items
fmt.Printf("{%s %s}\n", itemString[item.typ], item.val)
if l.state == nil {
break
}
}
}
// SendProbe creates a packet and sends it to the nameserver. It
// probe creates a packet and sends it to the nameserver. It
// returns a fingerprint.
func sendProbe(c *dns.Client, addr string, f *fingerprint) *fingerprint {
m := f.toProbe()
func probe(c *dns.Client, addr string, f *fingerprint) *fingerprint {
m := f.msg()
r, err := c.Exchange(m, addr)
if err != nil {
return errorToFingerprint(err)
}
return msgToFingerprint(r)
return toFingerprint(r)
}
// This leads to strings like: "miek.nl.,IN,A,QUERY,NOERROR,qr,aa,tc,RD,ad,cd,z,1,0,0,1,DO,4096,NSID"
@ -90,7 +67,7 @@ type fingerprint struct {
// String creates a (short) string representation of a dns message.
// If a bit is set we uppercase the name 'AD' otherwise it's lowercase 'ad'.
// This leads to strings like: "QUERY,NOERROR,qr,aa,tc,RD,ad,cd,z,1,0,0,1,DO,4096,NSID" // TODO fix doc
// This leads to strings like: ".,IN,NS,QUERY,NOERROR,qr,aa,tc,RD,ad,cd,z,1,0,0,1,DO,4096,NSID"
func (f *fingerprint) String() string {
if f == nil {
return "<nil>"
@ -155,7 +132,7 @@ func (f *fingerprint) StringNoSections() string {
return strings.Join(s[2:13], ",")
}
// SetString set the string to fp.. todo
// SetString sets the strings str to the fingerprint *f.
func (f *fingerprint) setString(str string) {
for i, s := range strings.Split(str, ",") {
switch i {
@ -208,7 +185,7 @@ func (f *fingerprint) setString(str string) {
case 19:
f.Nsid = s == strings.ToUpper("nsid")
default:
panic("unhandled fingerprint")
panic("unhandled fingerprint field")
}
}
return
@ -231,7 +208,8 @@ func errorToFingerprint(e error) *fingerprint {
return f
}
func msgToFingerprint(m *dns.Msg) *fingerprint {
// Convert a Msg to a fingerprint
func toFingerprint(m *dns.Msg) *fingerprint {
if m == nil {
return nil
}
@ -279,8 +257,8 @@ func msgToFingerprint(m *dns.Msg) *fingerprint {
// Create a dns message from a fingerprint string and
// a DNS question. The order of a string is always the same.
// QUERY,NOERROR,qr,aa,tc,RD,ad,ad,z,1,0,0,1,DO,4096,nsid
func (f *fingerprint) toProbe() *dns.Msg {
// .,IN,NS,QUERY,NOERROR,qr,aa,tc,RD,ad,ad,z,1,0,0,1,DO,4096,nsid
func (f *fingerprint) msg() *dns.Msg {
m := new(dns.Msg)
m.MsgHdr.Id = dns.Id()
m.Question = make([]dns.Question, 1)

View File

@ -1,81 +0,0 @@
// We handle the checking as a lexing program.
// We use the lexer like Rob Pike lectures about in this
// clip: http://www.youtube.com/watch?v=HxaD_trXwRE
package main
import (
"dns"
"fmt"
)
type itemType int
type item struct {
typ itemType
val string
}
const (
itemError itemType = iota
itemSoftware // the name of the DNS server software
itemVendor // vendor of the DNS software
itemVersionMajor // the major version of the software (empty if not determined)
itemVersionMinor // the minor version of the software (empty if not determined)
itemVersionPatch // the patch level of the software (empty if not determined)
)
var itemString = map[itemType]string{
itemError: "error",
itemSoftware: "software",
itemVendor: "vendor",
itemVersionMajor: "major",
itemVersionMinor: "minor",
itemVersionPatch: "patch",
}
// stateFn represents the state of the scanner as a function that returns the next state.
type stateFn func(*lexer) stateFn
type lexer struct {
client *dns.Client // client used.
addr string // addr of the server being scanned.
fp *fingerprint // fingerprint to test.
items chan item // channel of scanned items.
state stateFn // the next function to enter.
debug bool // if true, the fingerprints are printed.
}
func (l *lexer) probe() *fingerprint {
f := sendProbe(l.client, l.addr, l.fp)
if l.debug {
fmt.Printf(" QR fp: %s\n", f)
}
return f
}
func (l *lexer) emit(i *item) {
l.items <- *i
}
func (l *lexer) setString(s string) {
l.fp.setString(s)
if l.debug {
fmt.Printf(" Q fp: %s\n", s)
}
}
func (l *lexer) run() {
go func() {
for l.state != nil {
l.state = l.state(l)
}
close(l.items)
}()
}
func (l *lexer) verbose(s string) {
if l.debug {
fmt.Printf(" dns%s\n", s)
}
}

View File

@ -6,7 +6,6 @@ import (
"fmt"
"os"
"strconv"
"strings"
)
func q(w dns.RequestWriter, m *dns.Msg) {
@ -19,271 +18,39 @@ func q(w dns.RequestWriter, m *dns.Msg) {
}
func main() {
dnssec := flag.Bool("dnssec", false, "request DNSSEC records")
query := flag.Bool("question", false, "show question")
short := flag.Bool("short", false, "abbreviate long DNSKEY and RRSIG RRs")
check := flag.Bool("check", false, "check internal DNSSEC consistency")
port := flag.Int("port", 53, "port number to use")
aa := flag.Bool("aa", false, "set AA flag in query")
ad := flag.Bool("ad", false, "set AD flag in query")
cd := flag.Bool("cd", false, "set CD flag in query")
rd := flag.Bool("rd", true, "unset RD flag in query")
tcp := flag.Bool("tcp", false, "TCP mode")
nsid := flag.Bool("nsid", false, "ask for NSID")
fp := flag.Bool("fp", false, "enable server detection")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [@server] [qtype] [qclass] [name ...]\n", os.Args[0])
fmt.Fprintf(os.Stderr, "Usage: %s [-port 53] [@server]\n", os.Args[0])
flag.PrintDefaults()
}
conf, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
nameserver := "@" + conf.Servers[0]
qtype := uint16(0)
qclass := uint16(dns.ClassINET) // Default qclass
var qname []string
flag.Parse()
Flags:
for i := 0; i < flag.NArg(); i++ {
// If it starts with @ it is a nameserver
if flag.Arg(i)[0] == '@' {
nameserver = flag.Arg(i)
continue Flags
break
}
// First class, then type, to make ANY queries possible
// And if it looks like type, it is a type
if k, ok := dns.Str_rr[strings.ToUpper(flag.Arg(i))]; ok {
qtype = k
continue Flags
}
// If it looks like a class, it is a class
if k, ok := dns.Str_class[strings.ToUpper(flag.Arg(i))]; ok {
qclass = k
continue Flags
}
// If it starts with TYPExxx it is unknown rr
if strings.HasPrefix(flag.Arg(i), "TYPE") {
i, e := strconv.Atoi(string([]byte(flag.Arg(i))[4:]))
if e == nil {
qtype = uint16(i)
continue Flags
}
}
// Anything else is a qname
qname = append(qname, flag.Arg(i))
}
if len(qname) == 0 {
qname = make([]string, 1)
qname[0] = "."
qtype = dns.TypeNS
}
if qtype == 0 {
qtype = dns.TypeA
}
}
nameserver = string([]byte(nameserver)[1:]) // chop off @
nameserver += ":" + strconv.Itoa(*port)
// ipv6 todo
// We use the async query handling, just to show how
// it is to be used.
dns.HandleQueryFunc(".", q)
dns.ListenAndQuery(nil, nil)
c := dns.NewClient()
if *tcp {
c.Net = "tcp"
}
m := new(dns.Msg)
m.MsgHdr.Authoritative = *aa
m.MsgHdr.AuthenticatedData = *ad
m.MsgHdr.CheckingDisabled = *cd
m.MsgHdr.RecursionDesired = *rd
m.Question = make([]dns.Question, 1)
if *dnssec || *nsid {
o := new(dns.RR_OPT)
o.Hdr.Name = "."
o.Hdr.Rrtype = dns.TypeOPT
if *dnssec {
o.SetDo()
o.SetUDPSize(dns.DefaultMsgSize)
}
if *nsid {
o.SetNsid("")
}
m.Extra = append(m.Extra, o)
}
if *fp {
startParse(nameserver)
return
}
for _, v := range qname {
m.Question[0] = dns.Question{v, qtype, qclass}
m.Id = dns.Id()
if *query {
fmt.Printf("%s\n", msgToFingerprint(m))
fmt.Printf("%s\n", m.String())
}
c.Do(m, nameserver)
}
i := 0
forever:
for {
select {
case r := <-dns.DefaultReplyChan:
if r.Reply != nil {
if r.Reply.Rcode == dns.RcodeSuccess {
if r.Request.Id != r.Reply.Id {
fmt.Printf("Id mismatch\n")
}
}
if *check {
sigCheck(r.Reply, nameserver, *tcp)
nsecCheck(r.Reply)
}
if *short {
r.Reply = shortMsg(r.Reply)
}
fmt.Printf("%v", r.Reply)
}
i++
if i == len(qname) {
break forever
}
}
}
}
func sectionCheck(set []dns.RR, server string, tcp bool) {
for _, rr := range set {
if rr.Header().Rrtype == dns.TypeRRSIG {
rrset := getRRset(set, rr.Header().Name, rr.(*dns.RR_RRSIG).TypeCovered)
key := getKey(rr.(*dns.RR_RRSIG).SignerName, rr.(*dns.RR_RRSIG).KeyTag, server, tcp)
if key == nil {
fmt.Printf(";? DNSKEY %s/%d not found\n", rr.(*dns.RR_RRSIG).SignerName, rr.(*dns.RR_RRSIG).KeyTag)
continue
}
if err := rr.(*dns.RR_RRSIG).Verify(key, rrset); err != nil {
fmt.Printf(";- Bogus signature, %s does not validate (DNSKEY %s/%d)\n", shortSig(rr.(*dns.RR_RRSIG)), key.Header().Name, key.KeyTag())
} else {
fmt.Printf(";+ Secure signature, %s validates (DNSKEY %s/%d)\n", shortSig(rr.(*dns.RR_RRSIG)), key.Header().Name, key.KeyTag())
}
}
}
}
// Check if we have nsec3 records and if so, check them
func nsecCheck(in *dns.Msg) {
for _, r := range in.Answer {
if r.Header().Rrtype == dns.TypeNSEC3 {
goto Check
}
}
for _, r := range in.Ns {
if r.Header().Rrtype == dns.TypeNSEC3 {
goto Check
}
}
for _, r := range in.Extra {
if r.Header().Rrtype == dns.TypeNSEC3 {
goto Check
}
}
return
Check:
w, err := in.Nsec3Verify(in.Question[0])
switch w {
case dns.NSEC3_NXDOMAIN:
fmt.Printf(";+ Correct denial of existence (NSEC3/NXDOMAIN)\n")
case dns.NSEC3_NODATA:
fmt.Printf(";+ Correct denial of existence (NSEC3/NODATA)\n")
default:
// w == 0
if err != nil {
fmt.Printf(";- Incorrect denial of existence (NSEC3): %s\n",err.Error())
}
c := dns.NewClient()
fp := new(fingerprint)
for _, s := range fingerprints() {
fp.setString(s)
fp1 := probe(c, nameserver, fp)
println(s, "|", fp1.String())
}
}
// Check the sigs in the msg, get the signer's key (additional query), get the
// rrset from the message, check the signature(s)
func sigCheck(in *dns.Msg, server string, tcp bool) {
sectionCheck(in.Answer, server, tcp)
sectionCheck(in.Ns, server, tcp)
sectionCheck(in.Extra, server, tcp)
}
// Return the RRset belonging to the signature with name and type t
func getRRset(l []dns.RR, name string, t uint16) []dns.RR {
l1 := make([]dns.RR, 0)
for _, rr := range l {
if rr.Header().Name == name && rr.Header().Rrtype == t {
l1 = append(l1, rr)
}
}
return l1
}
// Get the key from the DNS (uses the local resolver) and return them.
// If nothing is found we return nil
func getKey(name string, keytag uint16, server string, tcp bool) *dns.RR_DNSKEY {
c := dns.NewClient()
if tcp {
c.Net = "tcp"
// A list of all the evil finger prints
func fingerprints() []string {
return []string {
".,CH,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,0,0,0,0,DO,4097,NSID", // general
"auThoRs.bInD.,CH,TXT,QUERY,NOERROR,qr,aa,tc,rd,ra,ad,cd,z,0,0,0,0,do,0,nsid", // case
"bind.,NONE,SOA,NOTIFY,NOERROR,qr,AA,tc,RD,ra,ad,cd,Z,0,0,0,0,do,0,nsid", // notify
}
m := new(dns.Msg)
m.SetQuestion(name, dns.TypeDNSKEY)
r, err := c.Exchange(m, server)
if err != nil {
return nil
}
for _, k := range r.Answer {
if k1, ok := k.(*dns.RR_DNSKEY); ok {
if k1.KeyTag() == keytag {
return k1
}
}
}
return nil
}
// shorten RRSIG to "miek.nl RRSIG(NS)"
func shortSig(sig *dns.RR_RRSIG) string {
return sig.Header().Name + " RRSIG(" + dns.Rr_str[sig.TypeCovered] + ")"
}
// Walk trough message and short Key data and Sig data
func shortMsg(in *dns.Msg) *dns.Msg {
for i := 0; i < len(in.Answer); i++ {
in.Answer[i] = shortRR(in.Answer[i])
}
for i := 0; i < len(in.Ns); i++ {
in.Ns[i] = shortRR(in.Ns[i])
}
for i := 0; i < len(in.Extra); i++ {
in.Extra[i] = shortRR(in.Extra[i])
}
return in
}
func shortRR(r dns.RR) dns.RR {
switch t := r.(type) {
case *dns.RR_DS:
t.Digest = "..."
case *dns.RR_DNSKEY:
t.PublicKey = "..."
case *dns.RR_RRSIG:
t.Signature = "..."
case *dns.RR_NSEC3:
t.Salt = "-" // Nobody cares
if len(t.TypeBitMap) > 5 {
t.TypeBitMap = t.TypeBitMap[1:5]
}
}
return r
}