1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

TXT records should check length at check/preview time (#947)

* TXT records should check length
* Add validation to TXT generator
* Split and validate long TXT targets
* Add a metaparameter to TXT records to indicate autosplit is requested.
* SPF_BUILDER marks TXT records as needing to be autosplit.
* Validate should check for overly-long TXT targets
This commit is contained in:
Tom Limoncelli
2020-11-18 07:05:26 -05:00
committed by GitHub
parent 550fa436ed
commit 13a1360779
8 changed files with 333 additions and 143 deletions

View File

@@ -19,6 +19,7 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
// flatten all spf records that have the "flatten" metadata
for _, txt := range apexTXTs {
var rec *spflib.SPFRecord
txtTarget := strings.Join(txt.TxtStrings, "")
if txt.Metadata["flatten"] != "" || txt.Metadata["split"] != "" {
if cache == nil {
cache, err = spflib.NewCache("spfcache.json")
@@ -26,13 +27,13 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
return []error{err}
}
}
rec, err = spflib.Parse(txt.GetTargetField(), cache)
rec, err = spflib.Parse(txtTarget, cache)
if err != nil {
errs = append(errs, err)
continue
}
}
if flatten, ok := txt.Metadata["flatten"]; ok && strings.HasPrefix(txt.GetTargetField(), "v=spf1") {
if flatten, ok := txt.Metadata["flatten"]; ok && strings.HasPrefix(txtTarget, "v=spf1") {
rec = rec.Flatten(flatten)
err = txt.SetTargetTXT(rec.TXT())
if err != nil {

View File

@@ -255,18 +255,12 @@ type Warning struct {
func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
for _, domain := range config.Domains {
pTypes := []string{}
txtMultiDissenters := []string{}
for _, provider := range domain.DNSProviderInstances {
pType := provider.ProviderType
// If NO_PURGE is in use, make sure this *isn't* a provider that *doesn't* support NO_PURGE.
if domain.KeepUnknown && providers.ProviderHasCapability(pType, providers.CantUseNOPURGE) {
errs = append(errs, fmt.Errorf("%s uses NO_PURGE which is not supported by %s(%s)", domain.Name, provider.Name, pType))
}
// Record if any providers do not support TXTMulti:
if !providers.ProviderHasCapability(pType, providers.CanUseTXTMulti) {
txtMultiDissenters = append(txtMultiDissenters, provider.Name)
}
}
// Normalize Nameservers.
@@ -335,12 +329,6 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
errs = append(errs, fmt.Errorf("TLSA MatchingType %d is invalid in record %s (domain %s)",
rec.TlsaMatchingType, rec.GetLabel(), domain.Name))
}
} else if rec.Type == "TXT" && len(txtMultiDissenters) != 0 && len(rec.TxtStrings) > 1 {
// There are providers that don't support TXTMulti yet there is
// a TXT record with multiple strings:
errs = append(errs,
fmt.Errorf("TXT records with multiple strings (label %v domain: %v) not supported by %s",
rec.GetLabel(), domain.Name, strings.Join(txtMultiDissenters, ",")))
}
// Populate FQDN:
@@ -353,6 +341,44 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
errs = append(errs, ers...)
}
// Split TXT targets that are >255 bytes (if permitted)
for _, domain := range config.Domains {
for _, rec := range domain.Records {
if rec.Type == "TXT" {
if txtAlgo, ok := rec.Metadata["txtSplitAlgorithm"]; ok {
rec.TxtNormalize(txtAlgo)
}
}
}
}
// Validate TXT records.
for _, domain := range config.Domains {
// Collect the names of providers that don't support TXTMulti:
txtMultiDissenters := []string{}
for _, provider := range domain.DNSProviderInstances {
pType := provider.ProviderType
if !providers.ProviderHasCapability(pType, providers.CanUseTXTMulti) {
txtMultiDissenters = append(txtMultiDissenters, provider.Name)
}
}
// Validate TXT records.
for _, rec := range domain.Records {
if rec.Type == "TXT" {
// If TXTMulti is required, all providers must support that feature.
if len(rec.TxtStrings) > 1 && len(txtMultiDissenters) > 0 {
errs = append(errs,
fmt.Errorf("TXT records with multiple strings not supported by %s (label=%q domain=%v)",
strings.Join(txtMultiDissenters, ","), rec.GetLabel(), domain.Name))
}
// Validate the record:
if err := models.ValidateTXT(rec); err != nil {
errs = append(errs, err)
}
}
}
}
// Process IMPORT_TRANSFORM
for _, domain := range config.Domains {
for _, rec := range domain.Records {