Skip to content

Commit

Permalink
Use hostname check from verify.go to handle patterns in TLS certs (#2…
Browse files Browse the repository at this point in the history
…3661) (#23675)

Previously, DNSNames in x509 certs with wildcards were not accepted. The function from Golang's `verify.go` is taken, so the check remains the same between Golang versions.

(cherry picked from commit 6291419)
  • Loading branch information
kvch authored Jan 26, 2021
1 parent 3205776 commit 1bee345
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 20 deletions.
47 changes: 30 additions & 17 deletions libbeat/common/transport/tlscommon/testdata/ca.crt
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIC/zCCAeegAwIBAgIJAIVZ8xw3LMNkMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNV
BAMMC21vcmVsbG8ub3ZoMB4XDTE5MDgwOTA5MzQwMFoXDTI5MDgwNjA5MzQwMFow
FjEUMBIGA1UEAwwLbW9yZWxsby5vdmgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQCoM2HYyuTTlu41SlgVO0Hdx7eUQevGSKO6pjPjN49/KKY1z/3DoKzr
seWaGOjiWUAqx/GHX8AsR9ToVoKGBbSNeDxT33pt3I9aCnnOPTt3yDIOlr4ZWnKq
NnNHwfydsMBfBAYgdU/L506KuNHJQ18Zey5+A0roTWyHUT48mQBsjetXg77RfDMB
MYVOWETfl70GKAaAlVGZfJHCkfBzYnPcEjqtcuU/7d27WZrSMhXifzHAEmm0KPER
EWdo4UHTK23wLY6dvkp2O5i0bKHv+PuLpqYrm7R7SWGhhwD651n5S5W20FHDow+d
js0yW2gqYsZZN6S1uAsJ8rdYAEPhK9J9AgMBAAGjUDBOMB0GA1UdDgQWBBQ6Lsen
0HbE+7M6iV9r8n5rZrbl4jAfBgNVHSMEGDAWgBQ6Lsen0HbE+7M6iV9r8n5rZrbl
4jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAgrLJnK4s/OVnh8CRk
GmikP+ZxhDs4k1nlr7+rTYkU0huoHK8p802w4zd74szYsHpo8kON/zSmFD7JpU4L
o2kseENqMsgrCPhF3+TDwf/Li43pbK162iAq8ZEpYnSXbQsRyP+Tz0lzoEoli6o7
6KVn4VNookLMyhGIAOmhfbNm0jG+B2zz+bvoTAe9CiDfvq1k0fnuKFzRtRsj09NJ
FNMhSc02N4EDrGpL5CYmEXjPZS3lUsoYPwbYlmUt3Bzuf5hI0mDHCt3BYKH1vFI4
W8/h9wwGn/yytsH21dkj41KEQK6N65gT9i0fBBiubuS2H1SVMMJ/J7PUqol278Ar
zGpS
MIIFhzCCA2+gAwIBAgIUL0vc8AdVKIcjap/RSpH21trR70swDQYJKoZIhvcNAQEL
BQAwUzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
DVNhbiBGcmFuY2lzY28xFzAVBgNVBAMMDmNhQGV4YW1wbGUuY29tMB4XDTIxMDEy
NTE2MzQ0OFoXDTMxMDEyMzE2MzQ0OFowUzELMAkGA1UEBhMCVVMxEzARBgNVBAgM
CkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFzAVBgNVBAMMDmNh
QGV4YW1wbGUuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAx0rP
p+sMWe3RehThE5Mh1s8uKsujG0q+Q62s4G4mBE5tQnmSS0LoezWuGMKNyjWQR4dt
IvicPZQfEhqOvdYAIA5fsQE8CMoXW50Q43kQlBUbvZH0yldUFtFtRLPD4RRtwB26
sUhWLUUCdk4mZBUmAuhMbIoov+TZ8/EZBdqjRBqM9p+k/C9xfitqXKmBWvWOmc0i
NUpxMjJ0C18vVcoAneiMQbB4iBNFviSLxrhnH9sno6IKG/WSCmOaPirmGzMr/PYQ
Wa4j69xQfGd4VBwolShI+fkoCmMQMk06XENUXo9V75sgbV0U0PAjBv4Kqye/r6s2
1wJKNnS8Ib4rBJAeh5PqebVmpgJUc8lAeC/4SE3Edw6yGILwuGnfZjZJeRgX+OMd
u5K29gvx4Kf0ZZ5F34vzsDwa8CGTTvdth8aNDhO4ETThxUtjqXSA91ewf93Tf3X5
Rzbg1K5hSHFVcd53Hec6/5Aqiw5PBARa2Ekj1ZW9PHHrSf/x+axyOyK+akUOoI8X
FlgImdr21pKZPSFNpvrYURRYDz8/ftFlcbsx32D3/uQZJW6FpvyguFWnVrGFm7He
ptWvYP2wM0XSOsHQXhogv09sgZhxgViHbc7/PZXOpTFlQt1MXygXVuf0eBUTiJI4
a595gF4F6Kx/ppBjWge+ZUUsnFjhHVhHvhzvncUCAwEAAaNTMFEwHQYDVR0OBBYE
FHg4mXfbBjMpE8mJUh/yPrfuD2yBMB8GA1UdIwQYMBaAFHg4mXfbBjMpE8mJUh/y
PrfuD2yBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAA+yu1mF
QoMeL5MwWr7O8q41Fu1n6BpRMm6KD0JOVWCJezW7anOJmcuySk6j2FRMPl3Z2fMH
p1I4420LlxN9H7QD5TVUJWCcujb2W9vhH9/R0qj9G9gkixfI0H/cGWd+Pe71ub5b
wxBTIe7U20uQ9imje8rShiZvgg3EocbWgPZcDnfHFjXVw/A1ocyIwpqjxooU8jiN
n1479sYR+R5TMc0zgZrTOKspcbNq5TEK138sFt79VB2d4oJNV/D0p0GktKpwisiZ
+xjr6iD2gZ9GGi0l0nQmtmLs+QAMuj+yOZX8CPwJlg7JuJYJ/nu0I5tBB1kOBml6
Jk2o5o3gU6FbfLc3j7aQ/kRP14ByfXqXPTVNbPxrVzFEsAx/NVWaVqbH9iwSye1G
M4kpvZ9RvEHHegNxoN3spKaJkpM056gTBJhWQIHGCOAqv7Izm68NqjSX6+wx92iZ
ujR1PR9pJdOYtjhdmQrWGLK7a06AaOo1v5iQOJ9SN48ucyN2hY2wIZ5IMdQC2I9P
IhIRTSX28cT0WRnH9Sdv9fWQLSfNwrcYWiTDd5+0ImspCC3HzwcTjqTCoT6utrmU
eHAzLPjoUu9FvnrZJW3eMOffvHSh3lK8yW3dv2HKFoXaBD5dL2irk4yacSAIIo2f
4T44UqQSs2U1ip1CHbP64vI1FRNfhDdZRU8w
-----END CERTIFICATE-----
51 changes: 51 additions & 0 deletions libbeat/common/transport/tlscommon/testdata/ca.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
22 changes: 22 additions & 0 deletions libbeat/common/transport/tlscommon/testdata/server.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDlTCCAX0CAQEwDQYJKoZIhvcNAQELBQAwUzELMAkGA1UEBhMCVVMxEzARBgNV
BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFzAVBgNVBAMM
DmNhQGV4YW1wbGUuY29tMB4XDTIxMDEyNTE2MzQ0OVoXDTMxMDEyMzE2MzQ0OVow
UjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNh
biBGcmFuY2lzY28xFjAUBgNVBAMMDSouZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcN
AQEBBQADgY0AMIGJAoGBALFuNygrGLLSnD//JRfU6xMDqgizeVdQqDlLaP/HxQ84
9RPWnjfbyx2M25JYcLvewPqKQ80lOYnMRhpvujmuKP7gQHNDWOsyXH5JljTX78Wb
I+nuVMeYjbUOh+6EgYNY59G5rH7xqgeu3y1YERfNdchEG8xjSxYeIZ7Ev6VMFF8r
AgMBAAEwDQYJKoZIhvcNAQELBQADggIBALyHDjVcY6Po1eHWTUCLLOW1ZzzkX4qu
gsfJM6qTIZIqh/O6tROGqH9kRw8SarIIZvtztfzuYtmQBE0qkBMzPzdN3x+3C4pz
jf2vsEKRqva9mf9y+JM0Mv0WUuPfusHxPKOCl1on71kP1GL1bYylKqazgVa2tAVa
78xs35YIuCM5apt0X+QO+Tnz/qfqJ7t3F7mP1aeCjYm8J20S8vKTYgkRkFX/8VJB
1zRPl0CAMyoHOMcrmb7wX8V1CIER7VBQ7h580B7/7okrw+Hr3xyMOA0w1DiRUQJE
biHBuDTRDmRg6W5nAwNLFLp/RfHttny0nEEcnzcjEStEKyDGbNg1W2ieWuIhgUza
L3W3ld9LDD9pMnQ8yYTMcL+J2Ir6ErhpGL3Hks42W2c/qYhvo3we6B2ADfsS7P+m
ku5W7/G2fDIlj6rtzaAeur+LSgsjU6kc1et2SJxjcJMPrS4xHxpAhJzD7h7f5N/B
RBc5cT2sE2vuUBRGkz0wC9AC2/kxmv4RwjsrYTY8rEOqHRkxDF18lfFocAoq7Hvr
lO6ft9/knzTQzKiizc6unXsLhUCvBzt50bA/gVLXmUmr1sncATKHWOLbvfRWat4I
0m52jlowgqnJPsXtl+wwNYHaw9gF71RTx/Ov2vZ8xm5SeBNkO8cpdAftETAEqpgp
fDlIVeywLvoN
-----END CERTIFICATE-----
15 changes: 15 additions & 0 deletions libbeat/common/transport/tlscommon/testdata/server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCxbjcoKxiy0pw//yUX1OsTA6oIs3lXUKg5S2j/x8UPOPUT1p43
28sdjNuSWHC73sD6ikPNJTmJzEYab7o5rij+4EBzQ1jrMlx+SZY01+/FmyPp7lTH
mI21DofuhIGDWOfRuax+8aoHrt8tWBEXzXXIRBvMY0sWHiGexL+lTBRfKwIDAQAB
AoGAaBKW5cfJl/JzVhJphn4MWL3YeXwUW4Pi+KBj+UwLKW+mSTmk2mzgyfd6P3AC
yB/Tn+GD/YutIUehgxYv7G9ceZC85EsPM6+1s887olgKNKbCiZZvrLBcBCzEhzkN
QpC2/cuOOVYdYYQJZp9RX7herAJ5aqxZHUUtCrudgfCiAckCQQDo37NhBBfUlLc4
LW3ryxydsh7MrTMU63+5IVtXosV3TFdWN9LC6CCarkILcOG5tmEmM6v1UQRAgCkm
lb+/3SrXAkEAwwz9+mcAU1lTTiy+dCJkKepviT4Ex+BFl0yJPfSN5+/Wg15DjwsN
vdE0H5nAT65aECiYy8V9DKNwHNcTIaZXzQJBAMvoPOBhPiCVC410MgC6e9cVRWTA
766Muuy26Y1l6HQac4r6HGEv8oSeuxPbhrsfmBdkPVjz1L5Juj6f9yOgHEcCQHMH
pHkaaay+D00ZQjDHX38AzUqJEtS1xRTXhFDPeyj/3uiWnQ0tHauGR1EjobDcSC0j
ZAk4rOjZMnMvvA6qRTkCQQCT6B0edwnMc9q/4XcdF+LptWRiYNbSKkrisb304N+d
lqbB76fGQY22onWcZEvcOmifmzmgj56QXSUot+fkNlVK
-----END RSA PRIVATE KEY-----
2 changes: 1 addition & 1 deletion libbeat/common/transport/tlscommon/tls_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func verifyHostname(cert *x509.Certificate, hostname string) error {
}

for _, name := range dnsnames {
if len(name) > 0 && len(hostname) > 0 && name == hostname {
if matchHostnames(name, hostname) {
if !validHostname(name, true) {
return fmt.Errorf("invalid hostname in cert")
}
Expand Down
15 changes: 14 additions & 1 deletion libbeat/common/transport/tlscommon/tls_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ func TestMakeVerifyServerConnection(t *testing.T) {
t.Fatalf("failed to open test certs: %+v", err)
}

testCA, errs := LoadCertificateAuthorities([]string{filepath.Join("testdata", "cacert.crt")})
testCA, errs := LoadCertificateAuthorities([]string{
filepath.Join("testdata", "ca.crt"),
filepath.Join("testdata", "cacert.crt"),
})
if len(errs) > 0 {
t.Fatalf("failed to load test certificate authorities: %+v", errs)
}
Expand Down Expand Up @@ -83,6 +86,15 @@ func TestMakeVerifyServerConnection(t *testing.T) {
expectedCallback: true,
expectedError: nil,
},
"default verification with certificates when required with correct wildcard cert": {
verificationMode: VerifyFull,
clientAuth: tls.RequireAndVerifyClientCert,
certAuthorities: testCA,
peerCerts: []*x509.Certificate{testCerts["wildcard"]},
serverName: "hello.example.com",
expectedCallback: true,
expectedError: nil,
},
"certificate verification with certificates when required with correct cert": {
verificationMode: VerifyCertificate,
clientAuth: tls.RequireAndVerifyClientCert,
Expand Down Expand Up @@ -181,6 +193,7 @@ func openTestCerts() (map[string]*x509.Certificate, error) {
"expired": "tls.crt",
"unknown authority": "unsigned_tls.crt",
"correct": "client1.crt",
"wildcard": "server.crt",
} {

certBytes, err := ioutil.ReadFile(filepath.Join("testdata", certname))
Expand Down
64 changes: 63 additions & 1 deletion libbeat/common/transport/tlscommon/validhostname.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,69 @@

package tlscommon

import "strings"
import (
"strings"
"unicode/utf8"
)

func matchHostnames(pattern, host string) bool {
pattern = toLowerCaseASCII(pattern)
host = toLowerCaseASCII(strings.TrimSuffix(host, "."))

if len(pattern) == 0 || len(host) == 0 {
return false
}

patternParts := strings.Split(pattern, ".")
hostParts := strings.Split(host, ".")

if len(patternParts) != len(hostParts) {
return false
}

for i, patternPart := range patternParts {
if i == 0 && patternPart == "*" {
continue
}
if patternPart != hostParts[i] {
return false
}
}

return true
}

// toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
// an explicitly ASCII function to avoid any sharp corners resulting from
// performing Unicode operations on DNS labels.
func toLowerCaseASCII(in string) string {
// If the string is already lower-case then there's nothing to do.
isAlreadyLowerCase := true
for _, c := range in {
if c == utf8.RuneError {
// If we get a UTF-8 error then there might be
// upper-case ASCII bytes in the invalid sequence.
isAlreadyLowerCase = false
break
}
if 'A' <= c && c <= 'Z' {
isAlreadyLowerCase = false
break
}
}

if isAlreadyLowerCase {
return in
}

out := []byte(in)
for i, c := range out {
if 'A' <= c && c <= 'Z' {
out[i] += 'a' - 'A'
}
}
return string(out)
}

// validHostname reports whether host is a valid hostname that can be matched or
// matched against according to RFC 6125 2.2, with some leniency to accommodate
Expand Down

0 comments on commit 1bee345

Please sign in to comment.