nsecx.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package dns
  2. import (
  3. "crypto/sha1"
  4. "hash"
  5. "io"
  6. "strings"
  7. )
  8. type saltWireFmt struct {
  9. Salt string `dns:"size-hex"`
  10. }
  11. // HashName hashes a string (label) according to RFC 5155. It returns the hashed string in
  12. // uppercase.
  13. func HashName(label string, ha uint8, iter uint16, salt string) string {
  14. saltwire := new(saltWireFmt)
  15. saltwire.Salt = salt
  16. wire := make([]byte, DefaultMsgSize)
  17. n, err := PackStruct(saltwire, wire, 0)
  18. if err != nil {
  19. return ""
  20. }
  21. wire = wire[:n]
  22. name := make([]byte, 255)
  23. off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
  24. if err != nil {
  25. return ""
  26. }
  27. name = name[:off]
  28. var s hash.Hash
  29. switch ha {
  30. case SHA1:
  31. s = sha1.New()
  32. default:
  33. return ""
  34. }
  35. // k = 0
  36. name = append(name, wire...)
  37. io.WriteString(s, string(name))
  38. nsec3 := s.Sum(nil)
  39. // k > 0
  40. for k := uint16(0); k < iter; k++ {
  41. s.Reset()
  42. nsec3 = append(nsec3, wire...)
  43. io.WriteString(s, string(nsec3))
  44. nsec3 = s.Sum(nil)
  45. }
  46. return toBase32(nsec3)
  47. }
  48. // Denialer is an interface that should be implemented by types that are used to denial
  49. // answers in DNSSEC.
  50. type Denialer interface {
  51. // Cover will check if the (unhashed) name is being covered by this NSEC or NSEC3.
  52. Cover(name string) bool
  53. // Match will check if the ownername matches the (unhashed) name for this NSEC3 or NSEC3.
  54. Match(name string) bool
  55. }
  56. // Cover implements the Denialer interface.
  57. func (rr *NSEC) Cover(name string) bool {
  58. return true
  59. }
  60. // Match implements the Denialer interface.
  61. func (rr *NSEC) Match(name string) bool {
  62. return true
  63. }
  64. // Cover implements the Denialer interface.
  65. func (rr *NSEC3) Cover(name string) bool {
  66. // FIXME(miek): check if the zones match
  67. // FIXME(miek): check if we're not dealing with parent nsec3
  68. hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
  69. labels := Split(rr.Hdr.Name)
  70. if len(labels) < 2 {
  71. return false
  72. }
  73. hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the dot
  74. if hash == rr.NextDomain {
  75. return false // empty interval
  76. }
  77. if hash > rr.NextDomain { // last name, points to apex
  78. // hname > hash
  79. // hname > rr.NextDomain
  80. // TODO(miek)
  81. }
  82. if hname <= hash {
  83. return false
  84. }
  85. if hname >= rr.NextDomain {
  86. return false
  87. }
  88. return true
  89. }
  90. // Match implements the Denialer interface.
  91. func (rr *NSEC3) Match(name string) bool {
  92. // FIXME(miek): Check if we are in the same zone
  93. hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
  94. labels := Split(rr.Hdr.Name)
  95. if len(labels) < 2 {
  96. return false
  97. }
  98. hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the .
  99. if hash == hname {
  100. return true
  101. }
  102. return false
  103. }