From ea3db974865b6340383b9236b5e5044b7be13747 Mon Sep 17 00:00:00 2001 From: Andrew Ayer Date: Wed, 4 May 2016 11:43:02 -0700 Subject: [PATCH] Only replace DNS label with placeholder if it's utterly unparsable e.g. contains control characters, Punycode conversion fails There are quite simply too many certs with bogus DNS labels out in the wild, and it just doesn't make sense to bother every .com domain holder because GoDaddy signed a cert with a DNS name like "www. just4funpartyrentals.com" It is highly unlikely any validator will ever match that DNS name. --- cmd/ctwatch/main.go | 5 +++-- identifiers.go | 39 ++++++++++++++++----------------------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/cmd/ctwatch/main.go b/cmd/ctwatch/main.go index dbfe536..25c4145 100644 --- a/cmd/ctwatch/main.go +++ b/cmd/ctwatch/main.go @@ -58,14 +58,15 @@ func setWatchDomains (domains []string) error { // For example, if we're monitoring sub.example.com, also monitor: // *.example.com // ?.example.com - // .example.com + // .example.com + // TODO: support for wildcards that are not the entire label (e.g. ac-*.fr) var parentDomain string if dot := strings.IndexRune(asciiDomain, '.'); dot != -1 { parentDomain = asciiDomain[dot:] } addWatchDomain("*" + parentDomain) addWatchDomain("?" + parentDomain) - addWatchDomain(ctwatch.InvalidDNSLabelPlaceholder + parentDomain) + addWatchDomain(ctwatch.UnparsableDNSLabelPlaceholder + parentDomain) } } return nil diff --git a/identifiers.go b/identifiers.go index b19d14f..61f58d0 100644 --- a/identifiers.go +++ b/identifiers.go @@ -8,7 +8,7 @@ import ( "golang.org/x/net/idna" ) -const InvalidDNSLabelPlaceholder = "" +const UnparsableDNSLabelPlaceholder = "" /* const ( @@ -61,25 +61,14 @@ func latin1ToUTF8 (value []byte) string { return string(runes) } -// Validate a DNS label. We are less strict than we could be, -// because the main purpose of this is to prevent nasty characters -// from getting through that could cause headaches later (e.g. NUL, -// control characters). In particular, we allow '_' (since it's -// quite common in hostnames despite being prohibited), '*' (since -// it's used to represent wildcards), and '?' (since it's used -// in CT to represent redacted labels). -func isValidDNSLabelChar (ch rune) bool { - return (ch >= 'A' && ch <= 'Z') || - (ch >= 'a' && ch <= 'z') || - (ch >= '0' && ch <= '9') || - ch == '-' || ch == '_'; +// Make sure the DNS label doesn't have any weird characters that +// could cause trouble during later processing. +func isSaneDNSLabelChar (ch rune) bool { + return ch == '\t' || (ch >= 32 && ch <= 126) } -func isValidDNSLabel (label string) bool { - if label == "*" || label == "?" { - return true - } +func isSaneDNSLabel (label string) bool { for _, ch := range label { - if !isValidDNSLabelChar(ch) { + if !isSaneDNSLabelChar(ch) { return false } } @@ -114,13 +103,17 @@ func trimTrailingDots (value string) string { return value[0:length] } -// Convert the DNS name to lower case and replace invalid labels with a placeholder +// Try to canonicalize/sanitize the DNS name: +// 1. Trim leading and trailing whitespace +// 2. Trim trailing dots +// 3. Convert to lower case +// 4. Replace totally nonsensical labels (e.g. having non-printable characters) with a placeholder func sanitizeDNSName (value string) string { value = strings.ToLower(trimTrailingDots(strings.TrimSpace(value))) labels := strings.Split(value, ".") for i, label := range labels { - if !isValidDNSLabel(label) { - labels[i] = InvalidDNSLabelPlaceholder + if !isSaneDNSLabel(label) { + labels[i] = UnparsableDNSLabelPlaceholder } } return strings.Join(labels, ".") @@ -131,10 +124,10 @@ func sanitizeUnicodeDNSName (value string) string { value = strings.ToLower(trimTrailingDots(strings.TrimSpace(value))) labels := strings.Split(value, ".") for i, label := range labels { - if asciiLabel, err := idna.ToASCII(label); err == nil && isValidDNSLabel(asciiLabel) { + if asciiLabel, err := idna.ToASCII(label); err == nil && isSaneDNSLabel(asciiLabel) { labels[i] = asciiLabel } else { - labels[i] = InvalidDNSLabelPlaceholder + labels[i] = UnparsableDNSLabelPlaceholder } } return strings.Join(labels, ".")