fix security issue with okhttp (#11749) · grpc/grpc-java@a0982ca
@@ -29,10 +29,13 @@
2929import java.util.List;
3030import java.util.Locale;
3131import java.util.regex.Pattern;
32+import java.nio.charset.StandardCharsets;
3233import javax.net.ssl.HostnameVerifier;
3334import javax.net.ssl.SSLException;
3435import javax.net.ssl.SSLSession;
3536import 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
6568public boolean verify(String host, SSLSession session) {
69+if (!isAscii(host)) {
70+return false;
71+ }
6672try {
6773Certificate[] certificates = session.getPeerCertificates();
6874return 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) {
7581return 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 */
100106private boolean verifyHostName(String hostName, X509Certificate certificate) {
101-hostName = hostName.toLowerCase(Locale.US);
107+hostName = Ascii.toLowerCase(hostName);
102108boolean hasDns = false;
103109List<String> altNames = getSubjectAltNames(certificate, ALT_DNS_NAME);
104110for (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.
203209204210if (!pattern.contains("*")) {
@@ -254,4 +260,13 @@ private boolean verifyHostName(String hostName, String pattern) {
254260// hostName matches pattern
255261return 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}