mirror of
				https://github.com/SSLMate/certspotter.git
				synced 2025-07-03 10:47:17 +02:00 
			
		
		
		
	Additional handling of pathological DNS names
1. Trim leading and trailing whitespace of DNS names. 2. Trim http:// and https:// prefixes. 3. If DNS name contains a slash, ALSO process the DNS name up to the first slash, since it's probably a URL.
This commit is contained in:
		
							parent
							
								
									3ec8a0a3db
								
							
						
					
					
						commit
						82167b8151
					
				| @ -86,6 +86,26 @@ func isValidDNSLabel (label string) bool { | |||||||
| 	return true | 	return true | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func trimHttpPrefixString (value string) string { | ||||||
|  | 	if strings.HasPrefix(value, "http://") { | ||||||
|  | 		return value[7:] | ||||||
|  | 	} else if strings.HasPrefix(value, "https://") { | ||||||
|  | 		return value[8:] | ||||||
|  | 	} else { | ||||||
|  | 		return value | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func trimHttpPrefixBytes (value []byte) []byte { | ||||||
|  | 	if bytes.HasPrefix(value, []byte("http://")) { | ||||||
|  | 		return value[7:] | ||||||
|  | 	} else if bytes.HasPrefix(value, []byte("https://")) { | ||||||
|  | 		return value[8:] | ||||||
|  | 	} else { | ||||||
|  | 		return value | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func trimTrailingDots (value string) string { | func trimTrailingDots (value string) string { | ||||||
| 	length := len(value) | 	length := len(value) | ||||||
| 	for length > 0 && value[length - 1] == '.' { | 	for length > 0 && value[length - 1] == '.' { | ||||||
| @ -96,7 +116,7 @@ func trimTrailingDots (value string) string { | |||||||
| 
 | 
 | ||||||
| // Convert the DNS name to lower case and replace invalid labels with a placeholder | // Convert the DNS name to lower case and replace invalid labels with a placeholder | ||||||
| func sanitizeDNSName (value string) string { | func sanitizeDNSName (value string) string { | ||||||
| 	value = strings.ToLower(trimTrailingDots(value)) | 	value = strings.ToLower(trimTrailingDots(strings.TrimSpace(value))) | ||||||
| 	labels := strings.Split(value, ".") | 	labels := strings.Split(value, ".") | ||||||
| 	for i, label := range labels { | 	for i, label := range labels { | ||||||
| 		if !isValidDNSLabel(label) { | 		if !isValidDNSLabel(label) { | ||||||
| @ -108,7 +128,7 @@ func sanitizeDNSName (value string) string { | |||||||
| 
 | 
 | ||||||
| // Like sanitizeDNSName, but labels that are Unicode are converted to Punycode. | // Like sanitizeDNSName, but labels that are Unicode are converted to Punycode. | ||||||
| func sanitizeUnicodeDNSName (value string) string { | func sanitizeUnicodeDNSName (value string) string { | ||||||
| 	value = strings.ToLower(trimTrailingDots(value)) | 	value = strings.ToLower(trimTrailingDots(strings.TrimSpace(value))) | ||||||
| 	labels := strings.Split(value, ".") | 	labels := strings.Split(value, ".") | ||||||
| 	for i, label := range labels { | 	for i, label := range labels { | ||||||
| 		if asciiLabel, err := idna.ToASCII(label); err == nil && isValidDNSLabel(asciiLabel) { | 		if asciiLabel, err := idna.ToASCII(label); err == nil && isValidDNSLabel(asciiLabel) { | ||||||
| @ -120,7 +140,7 @@ func sanitizeUnicodeDNSName (value string) string { | |||||||
| 	return strings.Join(labels, ".") | 	return strings.Join(labels, ".") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ids *Identifiers) addDnsSANnonull (value []byte) { | func (ids *Identifiers) addDnsSANfinal (value []byte) { | ||||||
| 	if ipaddr := parseIPAddrString(string(value)); ipaddr != nil { | 	if ipaddr := parseIPAddrString(string(value)); ipaddr != nil { | ||||||
| 		// Stupid CAs put IP addresses in DNS SANs because stupid Microsoft | 		// Stupid CAs put IP addresses in DNS SANs because stupid Microsoft | ||||||
| 		// used to not support IP address SANs.  Since there's no way for an IP | 		// used to not support IP address SANs.  Since there's no way for an IP | ||||||
| @ -141,7 +161,25 @@ func (ids *Identifiers) addDnsSANnonull (value []byte) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (ids *Identifiers) addDnsSANnonull (value []byte) { | ||||||
|  | 	if slashIndex := bytes.IndexByte(value, '/'); slashIndex != -1 { | ||||||
|  | 		// If the value contains a slash, then this might be a URL, | ||||||
|  | 		// so process the part of the value up to the first slash, | ||||||
|  | 		// which should be the domain.  Even though no client should | ||||||
|  | 		// ever successfully validate such a DNS name, the domain owner | ||||||
|  | 		// might still want to know about it. | ||||||
|  | 		ids.addDnsSANfinal(value[0:slashIndex]) | ||||||
|  | 	} | ||||||
|  | 	ids.addDnsSANfinal(value) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (ids *Identifiers) AddDnsSAN (value []byte) { | func (ids *Identifiers) AddDnsSAN (value []byte) { | ||||||
|  | 	// Trim http:// and https:// prefixes, which are all too common in the wild, | ||||||
|  | 	// so http://example.com becomes just example.com.  Even though clients | ||||||
|  | 	// should never successfully validate a DNS name like http://example.com, | ||||||
|  | 	// the owner of example.com might still want to know about it. | ||||||
|  | 	value = trimHttpPrefixBytes(value) | ||||||
|  | 
 | ||||||
| 	if nullIndex := bytes.IndexByte(value, 0); nullIndex != -1 { | 	if nullIndex := bytes.IndexByte(value, 0); nullIndex != -1 { | ||||||
| 		// If the value contains a null byte, process the part of | 		// If the value contains a null byte, process the part of | ||||||
| 		// the value up to the first null byte in addition to the | 		// the value up to the first null byte in addition to the | ||||||
| @ -152,7 +190,7 @@ func (ids *Identifiers) AddDnsSAN (value []byte) { | |||||||
| 	ids.addDnsSANnonull(value) | 	ids.addDnsSANnonull(value) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ids *Identifiers) addCNnonull (value string) { | func (ids *Identifiers) addCNfinal (value string) { | ||||||
| 	if ipaddr := parseIPAddrString(value); ipaddr != nil { | 	if ipaddr := parseIPAddrString(value); ipaddr != nil { | ||||||
| 		ids.IPAddrs = append(ids.IPAddrs, ipaddr) | 		ids.IPAddrs = append(ids.IPAddrs, ipaddr) | ||||||
| 	} else if !strings.ContainsRune(value, ' ') { | 	} else if !strings.ContainsRune(value, ' ') { | ||||||
| @ -161,7 +199,25 @@ func (ids *Identifiers) addCNnonull (value string) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (ids *Identifiers) addCNnonull (value string) { | ||||||
|  | 	if slashIndex := strings.IndexRune(value, '/'); slashIndex != -1 { | ||||||
|  | 		// If the value contains a slash, then this might be a URL, | ||||||
|  | 		// so process the part of the value up to the first slash, | ||||||
|  | 		// which should be the domain.  Even though no client should | ||||||
|  | 		// ever successfully validate such a DNS name, the domain owner | ||||||
|  | 		// might still want to know about it. | ||||||
|  | 		ids.addCNfinal(value[0:slashIndex]) | ||||||
|  | 	} | ||||||
|  | 	ids.addCNfinal(value) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (ids *Identifiers) AddCN (value string) { | func (ids *Identifiers) AddCN (value string) { | ||||||
|  | 	// Trim http:// and https:// prefixes, which are all too common in the wild, | ||||||
|  | 	// so http://example.com becomes just example.com.  Even though clients | ||||||
|  | 	// should never successfully validate a DNS name like http://example.com, | ||||||
|  | 	// the owner of example.com might still want to know about it. | ||||||
|  | 	value = trimHttpPrefixString(value) | ||||||
|  | 
 | ||||||
| 	if nullIndex := strings.IndexRune(value, 0); nullIndex != -1 { | 	if nullIndex := strings.IndexRune(value, 0); nullIndex != -1 { | ||||||
| 		// If the value contains a null byte, process the part of | 		// If the value contains a null byte, process the part of | ||||||
| 		// the value up to the first null byte in addition to the | 		// the value up to the first null byte in addition to the | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Andrew Ayer
						Andrew Ayer