|
|
|
@ -13,6 +13,7 @@ import (
|
|
|
|
|
|
|
|
|
|
"github.com/namecoin/ncdns/certdehydrate"
|
|
|
|
|
"github.com/namecoin/ncdns/util"
|
|
|
|
|
x509_compressed "github.com/namecoin/x509-compressed/x509"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Value struct {
|
|
|
|
@ -77,34 +78,34 @@ func parseTLSADehydrated(tlsa1dehydrated interface{}, v *Value) error {
|
|
|
|
|
|
|
|
|
|
func parseTLSADANE(tlsa1dane interface{}, v *Value) error {
|
|
|
|
|
if tlsa, ok := tlsa1dane.([]interface{}); ok {
|
|
|
|
|
// Format: ["443", "tcp", 1, 2, 3, "base64 certificate data"]
|
|
|
|
|
// Format: [1, 2, 3, "base64 certificate data"]
|
|
|
|
|
if len(tlsa) < 4 {
|
|
|
|
|
return fmt.Errorf("TLSA item must have six items")
|
|
|
|
|
return fmt.Errorf("TLSA item must have four items")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a1, ok := tlsa[0].(float64)
|
|
|
|
|
if !ok {
|
|
|
|
|
return fmt.Errorf("Third item in TLSA value must be an integer (usage)")
|
|
|
|
|
return fmt.Errorf("First item in TLSA value must be an integer (usage)")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a2, ok := tlsa[1].(float64)
|
|
|
|
|
if !ok {
|
|
|
|
|
return fmt.Errorf("Fourth item in TLSA value must be an integer (selector)")
|
|
|
|
|
return fmt.Errorf("Second item in TLSA value must be an integer (selector)")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a3, ok := tlsa[2].(float64)
|
|
|
|
|
if !ok {
|
|
|
|
|
return fmt.Errorf("Fifth item in TLSA value must be an integer (match type)")
|
|
|
|
|
return fmt.Errorf("Third item in TLSA value must be an integer (match type)")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a4, ok := tlsa[3].(string)
|
|
|
|
|
if !ok {
|
|
|
|
|
return fmt.Errorf("Sixth item in TLSA value must be a string (certificate)")
|
|
|
|
|
return fmt.Errorf("Fourth item in TLSA value must be a string (certificate)")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a4b, err := base64.StdEncoding.DecodeString(a4)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("Fourth item in DS value must be valid base64: %v", err)
|
|
|
|
|
return fmt.Errorf("Fourth item in TLSA value must be valid base64: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a4h := hex.EncodeToString(a4b)
|
|
|
|
@ -118,6 +119,36 @@ func parseTLSADANE(tlsa1dane interface{}, v *Value) error {
|
|
|
|
|
Certificate: strings.ToUpper(a4h),
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Handle compressed public keys specially
|
|
|
|
|
// Check if this TLSA is a public key preimage
|
|
|
|
|
if uint8(a2) == 1 && uint8(a3) == 0 {
|
|
|
|
|
pubDecompressed, err := x509_compressed.ParsePKIXPublicKey(a4b)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pubDecompressedBytes, err := x509.MarshalPKIXPublicKey(pubDecompressed)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pubDecompressedHex := hex.EncodeToString(pubDecompressedBytes)
|
|
|
|
|
|
|
|
|
|
if pubDecompressedHex == a4h {
|
|
|
|
|
// The pubkey wasn't compressed, so decompressing had no impact.
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
v.TLSA = append(v.TLSA, &dns.TLSA{
|
|
|
|
|
Hdr: dns.RR_Header{Name: "", Rrtype: dns.TypeTLSA, Class: dns.ClassINET,
|
|
|
|
|
Ttl: defaultTTL},
|
|
|
|
|
Usage: uint8(a1),
|
|
|
|
|
Selector: uint8(a2),
|
|
|
|
|
MatchingType: uint8(a3),
|
|
|
|
|
Certificate: strings.ToUpper(pubDecompressedHex),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
} else {
|
|
|
|
|
return fmt.Errorf("TLSA item must be an array")
|
|
|
|
|