diff --git a/pom.xml b/pom.xml index e1a57834c4618..cf8e996d137f5 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ 0.38 0.6 1.12.560 - 4.12.0 + 3.9.0 3.4.0 19.3.0.0 1.40 @@ -2554,7 +2554,6 @@ com.fasterxml.jackson.core:jackson-annotations com.fasterxml.jackson.core:jackson-core com.fasterxml.jackson.core:jackson-databind - org.jetbrains.kotlin:kotlin-stdlib-jdk8 diff --git a/presto-client/src/main/java/com/facebook/presto/client/JsonResponse.java b/presto-client/src/main/java/com/facebook/presto/client/JsonResponse.java index ac8075e6df206..8823fad06d74c 100644 --- a/presto-client/src/main/java/com/facebook/presto/client/JsonResponse.java +++ b/presto-client/src/main/java/com/facebook/presto/client/JsonResponse.java @@ -24,6 +24,7 @@ import javax.annotation.Nullable; import java.io.IOException; +import java.io.InterruptedIOException; import java.io.UncheckedIOException; import static com.google.common.base.MoreObjects.toStringHelper; @@ -145,6 +146,11 @@ public static JsonResponse execute(JsonCodec codec, OkHttpClient clien return new JsonResponse<>(response.code(), response.message(), response.headers(), body); } catch (IOException e) { + // OkHttp throws this after clearing the interrupt status + // TODO: remove after updating to Okio 1.15.0+ + if ((e instanceof InterruptedIOException) && "thread interrupted".equals(e.getMessage())) { + Thread.currentThread().interrupt(); + } throw new UncheckedIOException(e); } } diff --git a/presto-client/src/main/java/com/facebook/presto/client/OkHttpUtil.java b/presto-client/src/main/java/com/facebook/presto/client/OkHttpUtil.java index ede0ff646b4c7..78175f158dbb0 100644 --- a/presto-client/src/main/java/com/facebook/presto/client/OkHttpUtil.java +++ b/presto-client/src/main/java/com/facebook/presto/client/OkHttpUtil.java @@ -16,7 +16,6 @@ import com.facebook.airlift.security.pem.PemReader; import com.google.common.base.CharMatcher; import com.google.common.net.HostAndPort; -import okhttp.internal.tls.LegacyHostnameVerifier; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Credentials; @@ -238,7 +237,6 @@ public static void setupSsl( sslContext.init(keyManagers, new TrustManager[] {trustManager}, null); clientBuilder.sslSocketFactory(sslContext.getSocketFactory(), trustManager); - clientBuilder.hostnameVerifier(LegacyHostnameVerifier.INSTANCE); } catch (GeneralSecurityException | IOException e) { throw new ClientException("Error setting up SSL: " + e.getMessage(), e); diff --git a/presto-client/src/main/java/okhttp/internal/tls/DistinguishedNameParser.java b/presto-client/src/main/java/okhttp/internal/tls/DistinguishedNameParser.java deleted file mode 100644 index 4c5f22877da9e..0000000000000 --- a/presto-client/src/main/java/okhttp/internal/tls/DistinguishedNameParser.java +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -//CHECKSTYLE:OFF -package okhttp.internal.tls; -//CHECKSTYLE:ON - -import javax.security.auth.x500.X500Principal; - -/** - * A distinguished name (DN) parser. This parser only supports extracting a string value from a DN. - * It doesn't support values in the hex-string style. - * - * This class is based on the OkHttp library.The original source can be found here: - *[DistinguishedNameParser.java](https://github.com/square/okhttp/blob/83b9dd427535bce39be43a9e8224cdbc352d7427/okhttp/src/main/java/okhttp3/internal/tls/DistinguishedNameParser.java) - * - */ -final class DistinguishedNameParser -{ - private final String dn; - private final int length; - private int pos; - private int beg; - private int end; - - /** - * Temporary variable to store positions of the currently parsed item. - */ - private int cur; - - /** - * Distinguished name characters. - */ - private char[] chars; - - DistinguishedNameParser(X500Principal principal) - { - // RFC2253 is used to ensure we get attributes in the reverse - // order of the underlying ASN.1 encoding, so that the most - // significant values of repeated attributes occur first. - this.dn = principal.getName(X500Principal.RFC2253); - this.length = this.dn.length(); - } - - // gets next attribute type: (ALPHA 1*keychar) / oid - private String nextAT() - { - for (; pos < length && chars[pos] == ' '; pos++) { - // skip preceding space chars, they can present after - // comma or semicolon (compatibility with RFC 1779) - } - if (pos == length) { - return null; // reached the end of DN - } - - // mark the beginning of attribute type - beg = pos; - - // attribute type chars - pos++; - for (; pos < length && chars[pos] != '=' && chars[pos] != ' '; pos++) { - // we don't follow exact BNF syntax here: - // accept any char except space and '=' - } - if (pos >= length) { - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - - // mark the end of attribute type - end = pos; - - if (chars[pos] == ' ') { - for (; pos < length && chars[pos] != '=' && chars[pos] == ' '; pos++) { - // skip trailing space chars between attribute type and '=' - // (compatibility with RFC 1779) - } - - if (chars[pos] != '=' || pos == length) { - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - } - - pos++; //skip '=' char - - for (; pos < length && chars[pos] == ' '; pos++) { - // skip space chars between '=' and attribute value - // (compatibility with RFC 1779) - } - - // in case of oid attribute type skip its prefix: "oid." or "OID." - // (compatibility with RFC 1779) - if ((end - beg > 4) && (chars[beg + 3] == '.') - && (chars[beg] == 'O' || chars[beg] == 'o') - && (chars[beg + 1] == 'I' || chars[beg + 1] == 'i') - && (chars[beg + 2] == 'D' || chars[beg + 2] == 'd')) { - beg += 4; - } - - return new String(chars, beg, end - beg); - } - - // gets quoted attribute value: QUOTATION *( quotechar / pair ) QUOTATION - private String quotedAV() - { - pos++; - beg = pos; - end = beg; - while (true) { - if (pos == length) { - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - - if (chars[pos] == '"') { - // enclosing quotation was found - pos++; - break; - } - else if (chars[pos] == '\\') { - chars[end] = getEscaped(); - } - else { - // shift char: required for string with escaped chars - chars[end] = chars[pos]; - } - pos++; - end++; - } - - for (; pos < length && chars[pos] == ' '; pos++) { - // skip trailing space chars before comma or semicolon. - // (compatibility with RFC 1779) - } - - return new String(chars, beg, end - beg); - } - - // gets hex string attribute value: "#" hexstring - private String hexAV() - { - if (pos + 4 >= length) { - // encoded byte array must be not less then 4 c - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - - beg = pos; // store '#' position - pos++; - while (true) { - // check for end of attribute value - // looks for space and component separators - if (pos == length || chars[pos] == '+' || chars[pos] == ',' - || chars[pos] == ';') { - end = pos; - break; - } - - if (chars[pos] == ' ') { - end = pos; - pos++; - for (; pos < length && chars[pos] == ' '; pos++) { - // skip trailing space chars before comma or semicolon. - // (compatibility with RFC 1779) - } - break; - } - else if (chars[pos] >= 'A' && chars[pos] <= 'F') { - chars[pos] += 32; //to low case - } - - pos++; - } - - // verify length of hex string - // encoded byte array must be not less then 4 and must be even number - int hexLen = end - beg; // skip first '#' char - if (hexLen < 5 || (hexLen & 1) == 0) { - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - - // get byte encoding from string representation - byte[] encoded = new byte[hexLen / 2]; - for (int i = 0, p = beg + 1; i < encoded.length; p += 2, i++) { - encoded[i] = (byte) getByte(p); - } - return new String(chars, beg, hexLen); - } - // gets string attribute value: *( stringchar / pair) - private String escapedAV() - { - beg = pos; - end = pos; - while (true) { - if (pos >= length) { - // the end of DN has been found - return new String(chars, beg, end - beg); - } - - switch (chars[pos]) { - case '+': - case ',': - case ';': - // separator char has been found - return new String(chars, beg, end - beg); - case '\\': - // escaped char - chars[end++] = getEscaped(); - pos++; - break; - case ' ': - // need to figure out whether space defines - // the end of attribute value or not - cur = end; - - pos++; - chars[end++] = ' '; - - for (; pos < length && chars[pos] == ' '; pos++) { - chars[end++] = ' '; - } - if (pos == length || chars[pos] == ',' || chars[pos] == '+' - || chars[pos] == ';') { - // separator char or the end of DN has been found - return new String(chars, beg, cur - beg); - } - break; - default: - chars[end++] = chars[pos]; - pos++; - } - } - } - - // returns escaped char - private char getEscaped() - { - pos++; - if (pos == length) { - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - - switch (chars[pos]) { - case '"': - case '\\': - case ',': - case '=': - case '+': - case '<': - case '>': - case '#': - case ';': - case ' ': - case '*': - case '%': - case '_': - //FIXME: escaping is allowed only for leading or trailing space char - return chars[pos]; - default: - // RFC doesn't explicitly say that escaped hex pair is - // interpreted as UTF-8 char. It only contains an example of such DN. - return getUTF8(); - } - } - - // decodes UTF-8 char - // see http://www.unicode.org for UTF-8 bit distribution table - private char getUTF8() - { - int res = getByte(pos); - pos++; //FIXME tmp - - if (res < 128) { // one byte: 0-7F - return (char) res; - } - else if (res >= 192 && res <= 247) { - int count; - if (res <= 223) { // two bytes: C0-DF - count = 1; - res = res & 0x1F; - } - else if (res <= 239) { // three bytes: E0-EF - count = 2; - res = res & 0x0F; - } - else { // four bytes: F0-F7 - count = 3; - res = res & 0x07; - } - int b; - for (int i = 0; i < count; i++) { - pos++; - if (pos == length || chars[pos] != '\\') { - return 0x3F; //FIXME failed to decode UTF-8 char - return '?' - } - pos++; - - b = getByte(pos); - pos++; //FIXME tmp - if ((b & 0xC0) != 0x80) { - return 0x3F; //FIXME failed to decode UTF-8 char - return '?' - } - - res = (res << 6) + (b & 0x3F); - } - return (char) res; - } - else { - return 0x3F; //FIXME failed to decode UTF-8 char - return '?' - } - } - - // Returns byte representation of a char pair - // The char pair is composed of DN char in - // specified 'position' and the next char - // According to BNF syntax: - // hexchar = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" - // / "a" / "b" / "c" / "d" / "e" / "f" - private int getByte(int position) - { - if (position + 1 >= length) { - throw new IllegalStateException("Malformed DN: " + dn); - } - - int b1; - int b2; - - b1 = chars[position]; - if (b1 >= '0' && b1 <= '9') { - b1 = b1 - '0'; - } - else if (b1 >= 'a' && b1 <= 'f') { - b1 = b1 - 87; // 87 = 'a' - 10 - } - else if (b1 >= 'A' && b1 <= 'F') { - b1 = b1 - 55; // 55 = 'A' - 10 - } - else { - throw new IllegalStateException("Malformed DN: " + dn); - } - - b2 = chars[position + 1]; - if (b2 >= '0' && b2 <= '9') { - b2 = b2 - '0'; - } - else if (b2 >= 'a' && b2 <= 'f') { - b2 = b2 - 87; // 87 = 'a' - 10 - } - else if (b2 >= 'A' && b2 <= 'F') { - b2 = b2 - 55; // 55 = 'A' - 10 - } - else { - throw new IllegalStateException("Malformed DN: " + dn); - } - return (b1 << 4) + b2; - } - - /** - * Parses the DN and returns the most significant attribute value for an attribute type, or null - * if none found. - * - * @param attributeType attribute type to look for (e.g. "ca") - */ - public String findMostSpecific(String attributeType) - { - // Initialize internal state. - pos = 0; - beg = 0; - end = 0; - cur = 0; - chars = dn.toCharArray(); - - String attType = nextAT(); - if (attType == null) { - return null; - } - while (true) { - String attValue = ""; - - if (pos == length) { - return null; - } - switch (chars[pos]) { - case '"': - attValue = quotedAV(); - break; - case '#': - attValue = hexAV(); - break; - case '+': - case ',': - case ';': // compatibility with RFC 1779: semicolon can separate RDNs - //empty attribute value - break; - default: - attValue = escapedAV(); - } - - // Values are ordered from most specific to least specific - // due to the RFC2253 formatting. So take the first match - // we see. - if (attributeType.equalsIgnoreCase(attType)) { - return attValue; - } - - if (pos >= length) { - return null; - } - if (chars[pos] == ',' || chars[pos] == ';') { - //Do nothing - } else if (chars[pos] != '+') { - throw new IllegalStateException("Malformed DN: " + dn); - } - pos++; - attType = nextAT(); - if (attType == null) { - throw new IllegalStateException("Malformed DN: " + dn); - } - } - } -} diff --git a/presto-client/src/main/java/okhttp/internal/tls/LegacyHostnameVerifier.java b/presto-client/src/main/java/okhttp/internal/tls/LegacyHostnameVerifier.java deleted file mode 100644 index 1eac01a7db7f9..0000000000000 --- a/presto-client/src/main/java/okhttp/internal/tls/LegacyHostnameVerifier.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -//CHECKSTYLE:OFF -package okhttp.internal.tls; -//CHECKSTYLE:ON -import okhttp3.internal.tls.OkHostnameVerifier; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLSession; -import javax.security.auth.x500.X500Principal; - -import java.security.cert.Certificate; -import java.security.cert.CertificateParsingException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.regex.Pattern; - -public class LegacyHostnameVerifier - implements HostnameVerifier -{ - private static final int ALT_DNS_NAME = 2; - private static final int ALT_IPA_NAME = 7; - private static final Pattern VERIFY_AS_IP_ADDRESS = Pattern.compile( - "([0-9a-fA-F]*:[0-9a-fA-F:.]*)|([\\d.]+)"); - - public static final HostnameVerifier INSTANCE = new LegacyHostnameVerifier(); - - private LegacyHostnameVerifier() - { - } - - @Override - public boolean verify(String host, SSLSession session) - { - if (OkHostnameVerifier.INSTANCE.verify(host, session)) { - return true; - } - - // the CN cannot be used with IP addresses - if (verifyAsIpAddress(host)) { - return false; - } - - // try to verify using the legacy CN rules - try { - Certificate[] certificates = session.getPeerCertificates(); - X509Certificate certificate = (X509Certificate) certificates[0]; - - // only use CN if there are no alt names - if (!allSubjectAltNames(certificate).isEmpty()) { - return false; - } - - X500Principal principal = certificate.getSubjectX500Principal(); - // RFC 2818 advises using the most specific name for matching. - String cn = new DistinguishedNameParser(principal).findMostSpecific("cn"); - if (cn != null) { - return verifyHostName(host, cn); - } - - return false; - } - catch (SSLException e) { - return false; - } - } - - static boolean verifyAsIpAddress(String host) - { - return VERIFY_AS_IP_ADDRESS.matcher(host).matches(); - } - - /** - * Returns true if {@code certificate} matches {@code ipAddress}. - */ - private boolean verifyIpAddress(String ipAddress, X509Certificate certificate) - { - List altNames = getSubjectAltNames(certificate, ALT_IPA_NAME); - for (int i = 0, size = altNames.size(); i < size; i++) { - if (ipAddress.equalsIgnoreCase(altNames.get(i))) { - return true; - } - } - return false; - } - - private boolean verifyHostName(String hostName, X509Certificate certificate) - { - hostName = hostName.toLowerCase(Locale.US); - boolean hasDns = false; - List altNames = getSubjectAltNames(certificate, ALT_DNS_NAME); - for (int i = 0, size = altNames.size(); i < size; i++) { - hasDns = true; - if (verifyHostName(hostName, altNames.get(i))) { - return true; - } - } - - if (!hasDns) { - X500Principal principal = certificate.getSubjectX500Principal(); - // RFC 2818 advises using the most specific name for matching. - String cn = new DistinguishedNameParser(principal).findMostSpecific("cn"); - if (cn != null) { - return verifyHostName(hostName, cn); - } - } - - return false; - } - - public static List allSubjectAltNames(X509Certificate certificate) - { - List altIpaNames = getSubjectAltNames(certificate, ALT_IPA_NAME); - List altDnsNames = getSubjectAltNames(certificate, ALT_DNS_NAME); - List result = new ArrayList<>(altIpaNames.size() + altDnsNames.size()); - result.addAll(altIpaNames); - result.addAll(altDnsNames); - return result; - } - - private static List getSubjectAltNames(X509Certificate certificate, int type) - { - List result = new ArrayList<>(); - try { - Collection subjectAltNames = certificate.getSubjectAlternativeNames(); - if (subjectAltNames == null) { - return Collections.emptyList(); - } - for (Object subjectAltName : subjectAltNames) { - List entry = (List) subjectAltName; - if (entry == null || entry.size() < 2) { - continue; - } - Integer altNameType = (Integer) entry.get(0); - if (altNameType == null) { - continue; - } - if (altNameType == type) { - String altName = (String) entry.get(1); - if (altName != null) { - result.add(altName); - } - } - } - return result; - } - catch (CertificateParsingException e) { - return Collections.emptyList(); - } - } - - /** - * Returns {@code true} iff {@code hostName} matches the domain name {@code pattern}. - * - * @param hostName lower-case host name. - * @param pattern domain name pattern from certificate. May be a wildcard pattern such as - * {@code *.android.com}. - */ - private boolean verifyHostName(String hostName, String pattern) - { - // Basic sanity checks - // Check length == 0 instead of .isEmpty() to support Java 5. - if ((hostName == null) || (hostName.length() == 0) || (hostName.startsWith(".")) - || (hostName.endsWith(".."))) { - // Invalid domain name - return false; - } - if ((pattern == null) || (pattern.length() == 0) || (pattern.startsWith(".")) - || (pattern.endsWith(".."))) { - // Invalid pattern/domain name - return false; - } - - // Normalize hostName and pattern by turning them into absolute domain names if they are not - // yet absolute. This is needed because server certificates do not normally contain absolute - // names or patterns, but they should be treated as absolute. At the same time, any hostName - // presented to this method should also be treated as absolute for the purposes of matching - // to the server certificate. - // www.android.com matches www.android.com - // www.android.com matches www.android.com. - // www.android.com. matches www.android.com. - // www.android.com. matches www.android.com - if (!hostName.endsWith(".")) { - hostName += '.'; - } - if (!pattern.endsWith(".")) { - pattern += '.'; - } - // hostName and pattern are now absolute domain names. - - pattern = pattern.toLowerCase(Locale.US); - // hostName and pattern are now in lower case -- domain names are case-insensitive. - - if (!pattern.contains("*")) { - // Not a wildcard pattern -- hostName and pattern must match exactly. - return hostName.equals(pattern); - } - // Wildcard pattern - - // WILDCARD PATTERN RULES: - // 1. Asterisk (*) is only permitted in the left-most domain name label and must be the - // only character in that label (i.e., must match the whole left-most label). - // For example, *.example.com is permitted, while *a.example.com, a*.example.com, - // a*b.example.com, a.*.example.com are not permitted. - // 2. Asterisk (*) cannot match across domain name labels. - // For example, *.example.com matches test.example.com but does not match - // sub.test.example.com. - // 3. Wildcard patterns for single-label domain names are not permitted. - - if ((!pattern.startsWith("*.")) || (pattern.indexOf('*', 1) != -1)) { - // Asterisk (*) is only permitted in the left-most domain name label and must be the only - // character in that label - return false; - } - - // Optimization: check whether hostName is too short to match the pattern. hostName must be at - // least as long as the pattern because asterisk must match the whole left-most label and - // hostName starts with a non-empty label. Thus, asterisk has to match one or more characters. - if (hostName.length() < pattern.length()) { - // hostName too short to match the pattern. - return false; - } - - if ("*.".equals(pattern)) { - // Wildcard pattern for single-label domain name -- not permitted. - return false; - } - - // hostName must end with the region of pattern following the asterisk. - String suffix = pattern.substring(1); - if (!hostName.endsWith(suffix)) { - // hostName does not end with the suffix - return false; - } - - // Check that asterisk did not match across domain name labels. - int suffixStartIndexInHostName = hostName.length() - suffix.length(); - if ((suffixStartIndexInHostName > 0) - && (hostName.lastIndexOf('.', suffixStartIndexInHostName - 1) != -1)) { - // Asterisk is matching across domain name labels -- not permitted. - return false; - } - - // hostName matches pattern - return true; - } -} diff --git a/presto-native-sidecar-plugin/pom.xml b/presto-native-sidecar-plugin/pom.xml index 958c3ef895aa2..b29409050be23 100644 --- a/presto-native-sidecar-plugin/pom.xml +++ b/presto-native-sidecar-plugin/pom.xml @@ -55,12 +55,6 @@ com.squareup.okhttp3 okhttp - - - org.jetbrains - annotations - -