diff --git a/dnssec.go b/dnssec.go index 87b7b0b0..1541beb8 100644 --- a/dnssec.go +++ b/dnssec.go @@ -8,7 +8,7 @@ // // Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit // to an request. -// +// // m := new(dns.Msg) // m.SetEdns0(4096, true) // @@ -61,7 +61,7 @@ const ( const ( _ = iota SHA1 // RFC 4034 - SHA256 // RFC 4509 + SHA256 // RFC 4509 GOST94 // RFC 5933 SHA384 // Experimental SHA512 // Experimental @@ -309,7 +309,7 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error { // Verify validates an RRSet with the signature and key. This is only the // cryptographic test, the signature validity period must be checked separately. -// This function copies the rdata of some RRs (to lowercase domain names) for the validation to work. +// This function copies the rdata of some RRs (to lowercase domain names) for the validation to work. func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error { // First the easy checks if len(rrset) == 0 { @@ -423,7 +423,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error { return ErrAlg } -// ValidityPeriod uses RFC1982 serial arithmetic to calculate +// ValidityPeriod uses RFC1982 serial arithmetic to calculate // if a signature period is valid. func (rr *RRSIG) ValidityPeriod() bool { utc := time.Now().UTC().Unix() @@ -443,7 +443,7 @@ func (s *RRSIG) sigBuf() []byte { return sigbuf } -// setPublicKeyInPrivate sets the public key in the private key. +// setPublicKeyInPrivate sets the public key in the private key. func (k *DNSKEY) setPublicKeyInPrivate(p PrivateKey) bool { switch t := p.(type) { case *dsa.PrivateKey: @@ -606,7 +606,7 @@ func exponentToBuf(_E int) []byte { return buf } -// Set the public key for X and Y for Curve. The two +// Set the public key for X and Y for Curve. The two // values are just concatenated. func curveToBuf(_X, _Y *big.Int) []byte { buf := _X.Bytes() @@ -614,7 +614,7 @@ func curveToBuf(_X, _Y *big.Int) []byte { return buf } -// Set the public key for X and Y for Curve. The two +// Set the public key for X and Y for Curve. The two // values are just concatenated. func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte { t := byte((len(_G.Bytes()) - 64) / 8) @@ -720,3 +720,15 @@ var AlgorithmToString = map[uint8]string{ // Map of algorithm strings. var StringToAlgorithm = reverseInt8(AlgorithmToString) + +// Map for hash names. +var HashToString = map[uint8]string{ + SHA1: "SHA1", + SHA256: "SHA256", + GOST94: "GOST94", + SHA384: "SHA384", + SHA512: "SHA512", +} + +// Map of hash strings. +var StringToHash = reverseInt8(HashToString) diff --git a/edns.go b/edns.go index 6fb71894..fbcdd06a 100644 --- a/edns.go +++ b/edns.go @@ -38,6 +38,9 @@ const ( EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt EDNS0NSID = 0x3 // nsid (RFC5001) EDNS0SUBNET = 0x50fa // client-subnet draft: http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-01 + EDNS0DAU = 0x4 // DNSSEC Algorithm Understood - not the final number! + EDNS0DHU = 0x5 // DS Hash Understood - not the final number! + EDNS0N3U = 0x6 // NSEC3 Hash Understood - not the final number! _DO = 1 << 7 // dnssec ok ) @@ -74,7 +77,15 @@ func (rr *OPT) String() string { case *EDNS0_SUBNET: s += "\n; SUBNET: " + o.String() case *EDNS0_UL: - s += "\n; LEASE: " + o.String() + s += "\n; UPDATE LEASE: " + o.String() + case *EDNS0_LLQ: + s += "\n; LONG LIVED QUERIES: " + o.String() + case *EDNS0_DAU: + s += "\n; DNSSEC ALGORITHM UNDERSTOOD: " + o.String() + case *EDNS0_DHU: + s += "\n; DS HASH UNDERSTOOD: " + o.String() + case *EDNS0_N3U: + s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String() } } return s @@ -391,3 +402,89 @@ func (e *EDNS0_LLQ) String() string { " " + strconv.FormatUint(uint64(e.LeaseLife), 10) return s } + +type EDNS0_DAU struct { + Code uint16 // Always EDNS0DAU + AlgCode []uint8 +} + +func (e *EDNS0_DAU) Option() uint16 { + return EDNS0DAU +} +func (e *EDNS0_DAU) pack() ([]byte, error) { + return e.AlgCode, nil +} + +func (e *EDNS0_DAU) unpack(b []byte) { + e.AlgCode = b +} + +func (e *EDNS0_DAU) String() string { + s := "" + for i := 0; i < len(e.AlgCode); i++ { + if a, ok := AlgorithmToString[e.AlgCode[i]]; ok { + s += " " + a + } else { + s += " " + strconv.Itoa(int(e.AlgCode[i])) + } + } + return s + +} + +type EDNS0_DHU struct { + Code uint16 // Always EDNS0DHU + AlgCode []uint8 +} + +func (e *EDNS0_DHU) Option() uint16 { + return EDNS0DHU +} +func (e *EDNS0_DHU) pack() ([]byte, error) { + return e.AlgCode, nil +} + +func (e *EDNS0_DHU) unpack(b []byte) { + e.AlgCode = b +} + +func (e *EDNS0_DHU) String() string { + s := "" + for i := 0; i < len(e.AlgCode); i++ { + if a, ok := HashToString[e.AlgCode[i]]; ok { + s += " " + a + } else { + s += " " + strconv.Itoa(int(e.AlgCode[i])) + } + } + return s +} + +type EDNS0_N3U struct { + Code uint16 // Always EDNS0N3U + AlgCode []uint8 +} + +func (e *EDNS0_N3U) Option() uint16 { + return EDNS0N3U +} +func (e *EDNS0_N3U) pack() ([]byte, error) { + return e.AlgCode, nil +} + +func (e *EDNS0_N3U) unpack(b []byte) { + e.AlgCode = b +} + +func (e *EDNS0_N3U) String() string { + // Re-use the hash map + s := "" + for i := 0; i < len(e.AlgCode); i++ { + if a, ok := HashToString[e.AlgCode[i]]; ok { + s += " " + a + } else { + s += " " + strconv.Itoa(int(e.AlgCode[i])) + } + } + return s +} diff --git a/msg.go b/msg.go index b058c346..f1b25205 100644 --- a/msg.go +++ b/msg.go @@ -760,6 +760,21 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er e.unpack(msg[off1 : off1+int(optlen)]) edns = append(edns, e) off = off1 + int(optlen) + case EDNS0DAU: + e := new(EDNS0_DAU) + e.unpack(msg[off1 : off1+int(optlen)]) + edns = append(edns, e) + off = off1 + int(optlen) + case EDNS0DHU: + e := new(EDNS0_DHU) + e.unpack(msg[off1 : off1+int(optlen)]) + edns = append(edns, e) + off = off1 + int(optlen) + case EDNS0N3U: + e := new(EDNS0_N3U) + e.unpack(msg[off1 : off1+int(optlen)]) + edns = append(edns, e) + off = off1 + int(optlen) default: // do nothing? off = off1 + int(optlen)