nsecx.go 2.7 KB

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