fix security issue with okhttp (#11749) · grpc/grpc-java@a0982ca

@@ -29,10 +29,13 @@

2929

import java.util.List;

3030

import java.util.Locale;

3131

import java.util.regex.Pattern;

32+

import java.nio.charset.StandardCharsets;

3233

import javax.net.ssl.HostnameVerifier;

3334

import javax.net.ssl.SSLException;

3435

import javax.net.ssl.SSLSession;

3536

import javax.security.auth.x500.X500Principal;

37+

import com.google.common.base.Utf8;

38+

import com.google.common.base.Ascii;

36393740

/**

3841

* A HostnameVerifier consistent with <a

@@ -63,6 +66,9 @@ private OkHostnameVerifier() {

63666467

@Override

6568

public boolean verify(String host, SSLSession session) {

69+

if (!isAscii(host)) {

70+

return false;

71+

}

6672

try {

6773

Certificate[] certificates = session.getPeerCertificates();

6874

return verify(host, (X509Certificate) certificates[0]);

@@ -71,7 +77,7 @@ public boolean verify(String host, SSLSession session) {

7177

}

7278

}

737974-

public boolean verify(String host, X509Certificate certificate) {

80+

private boolean verify(String host, X509Certificate certificate) {

7581

return verifyAsIpAddress(host)

7682

? verifyIpAddress(host, certificate)

7783

: verifyHostName(host, certificate);

@@ -98,7 +104,7 @@ private boolean verifyIpAddress(String ipAddress, X509Certificate certificate) {

98104

* Returns true if {@code certificate} matches {@code hostName}.

99105

*/

100106

private boolean verifyHostName(String hostName, X509Certificate certificate) {

101-

hostName = hostName.toLowerCase(Locale.US);

107+

hostName = Ascii.toLowerCase(hostName);

102108

boolean hasDns = false;

103109

List<String> altNames = getSubjectAltNames(certificate, ALT_DNS_NAME);

104110

for (int i = 0, size = altNames.size(); i < size; i++) {

@@ -198,7 +204,7 @@ private boolean verifyHostName(String hostName, String pattern) {

198204

}

199205

// hostName and pattern are now absolute domain names.

200206201-

pattern = pattern.toLowerCase(Locale.US);

207+

pattern = Ascii.toLowerCase(pattern);

202208

// hostName and pattern are now in lower case -- domain names are case-insensitive.

203209204210

if (!pattern.contains("*")) {

@@ -254,4 +260,13 @@ private boolean verifyHostName(String hostName, String pattern) {

254260

// hostName matches pattern

255261

return true;

256262

}

263+264+

/**

265+

* Returns true if {@code input} is an ASCII string.

266+

* @param input the string to check.

267+

*/

268+

private static boolean isAscii(String input) {

269+

// Only ASCII characters are 1 byte in UTF-8.

270+

return Utf8.encodedLength(input) == input.length();

271+

}

257272

}