From 4cf4d34ca6db590e09a405fa4f8ff64aa83a6328 Mon Sep 17 00:00:00 2001 From: Florian Ritterhoff <32478819+fritterhoff@users.noreply.github.com> Date: Sat, 31 Dec 2022 12:13:44 +0100 Subject: [PATCH] Add missing MD5 support (#1866) --- docs/_providers/axfrddns.md | 4 +++ providers/axfrddns/axfrddnsProvider.go | 6 ++++ providers/axfrddns/md5Provider.go | 46 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 providers/axfrddns/md5Provider.go diff --git a/docs/_providers/axfrddns.md b/docs/_providers/axfrddns.md index 2f055fe2d..b3dfe50a4 100644 --- a/docs/_providers/axfrddns.md +++ b/docs/_providers/axfrddns.md @@ -211,3 +211,7 @@ When AutoDNSSEC is enabled, the AXFR+DDNS provider will emit a warning when no R When AutoDNSSEC is disabled, the AXFR+DDNS provider will emit a warning when RRSIG, DNSKEY or NSEC records are found in the zone. When AutoDNSSEC is not enabled or disabled, no checking is done. + +## FYI: MD5 Support + +By default the used DNS Go package by miekg has deprecated supporting the (insecure) MD5 algorithm [https://github.com/miekg/dns/commit/93945c284489394b77653323d11d5de83a2a6fb5](Link). Some providers like the Leibniz Supercomputing Centre (LRZ) located in Munich still use this algorithm to authenticate internal dynamic DNS updates. To compensate the lack of MD5 a custom MD5 TSIG Provider was added into DNSControl. \ No newline at end of file diff --git a/providers/axfrddns/axfrddnsProvider.go b/providers/axfrddns/axfrddnsProvider.go index 2abf4e630..433455f92 100644 --- a/providers/axfrddns/axfrddnsProvider.go +++ b/providers/axfrddns/axfrddnsProvider.go @@ -232,6 +232,9 @@ func (c *axfrddnsProvider) FetchZoneRecords(domain string) ([]dns.RR, error) { transfer.TsigSecret = map[string]string{c.transferKey.id: c.transferKey.secret} request.SetTsig(c.transferKey.id, c.transferKey.algo, 300, time.Now().Unix()) + if c.transferKey.algo == dns.HmacMD5 { + transfer.TsigProvider = md5Provider(c.transferKey.secret) + } } envelope, err := transfer.In(request, c.master) @@ -428,6 +431,9 @@ func (c *axfrddnsProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod client.TsigSecret = map[string]string{c.updateKey.id: c.updateKey.secret} update.SetTsig(c.updateKey.id, c.updateKey.algo, 300, time.Now().Unix()) + if c.updateKey.algo == dns.HmacMD5 { + client.TsigProvider = md5Provider(c.updateKey.secret) + } } msg, _, err := client.Exchange(update, c.master) diff --git a/providers/axfrddns/md5Provider.go b/providers/axfrddns/md5Provider.go new file mode 100644 index 000000000..335b0bb50 --- /dev/null +++ b/providers/axfrddns/md5Provider.go @@ -0,0 +1,46 @@ +package axfrddns + +import ( + "crypto/hmac" + "crypto/md5" //#nosec + "encoding/base64" + "encoding/hex" + + "github.com/miekg/dns" +) + +type md5Provider string + +func fromBase64(s []byte) (buf []byte, err error) { + buflen := base64.StdEncoding.DecodedLen(len(s)) + buf = make([]byte, buflen) + n, err := base64.StdEncoding.Decode(buf, s) + buf = buf[:n] + return +} + +func (key md5Provider) Generate(msg []byte, _ *dns.TSIG) ([]byte, error) { + rawsecret, err := fromBase64([]byte(key)) + if err != nil { + return nil, err + } + h := hmac.New(md5.New, rawsecret) + + h.Write(msg) + return h.Sum(nil), nil +} + +func (key md5Provider) Verify(msg []byte, t *dns.TSIG) error { + b, err := key.Generate(msg, t) + if err != nil { + return err + } + mac, err := hex.DecodeString(t.MAC) + if err != nil { + return err + } + if !hmac.Equal(b, mac) { + return dns.ErrSig + } + return nil +}