2016-11-16 1 views
3

올바른 암호 제품군을 사용하도록 관리되었지만 프로세스에서 호스트 이름 비교를 위반했습니다. 여기 Android 7에서 더 이상 사용되지 않는 암호 제품군을 사용한 후 호스트 이름이 일치하지 않음. org.apache.http (Apache HttpClient 4.0)

코드 내가 시작하기 전에 다음과 같습니다 의한 지원 클라이언트를 필요로하는 웹 서버에

javax.net.ssl.SSLHandshakeException: Handshake failed 
    at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429) 
    at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:406) 
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:170) 
    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169) 
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:366) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:470) 
    ... 
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x9f7a03c0: Failure in SSL library, usually a protocol error 
error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE (external/boringssl/src/ssl/s3_pkt.c:610 0x9c571b00:0x00000001) 
error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO (external/boringssl/src/ssl/s3_clnt.c:764 0x9c614196:0x00000000) 
    at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
    at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357) 
     ... 19 more 

이 분명히 있습니다 :

HttpParams params = new BasicHttpParams(); 
HttpConnectionParams.setConnectionTimeout(params, 10000); 
HttpConnectionParams.setSoTimeout(params, 20000); 

DefaultHttpClient client = new DefaultHttpClient(params); 

HttpPost request = new HttpPost(url); 
... 
HttpResponse response = client.execute(request); 
... 

안드로이드 (7)을 시작으로, 나는 다음과 같은 오류가 발생했다 RC4, through Android 6 (api 23) 만 지원됩니다. 아쉽게도 현재 웹 서버를 업그레이드 할 수 없으므로 앱에서 필요한 암호 모음을 활성화해야합니다. 이 성공적으로 필요한 암호화 제품군을 추가

// HttpParams params is same as before 

DefaultHttpClient client = new DefaultHttpClient(params); 

ClientConnectionManager connManager = client.getConnectionManager(); 
SchemeRegistry schemeRegistry = connManager.getSchemeRegistry(); 
Scheme scheme = schemeRegistry.getScheme("https"); 
final SSLSocketFactory impl = (SSLSocketFactory) scheme.getSocketFactory(); 

SocketFactory sf = new SocketFactory() { 

    @Override 
    public Socket createSocket() throws IOException { 
     SSLSocket socket = (SSLSocket) impl.createSocket(); 
     ArrayList<String> list = new ArrayList<>(Arrays.asList(socket.getEnabledCipherSuites())); 
     list.add("SSL_RSA_WITH_RC4_128_SHA"); 
     socket.setEnabledCipherSuites(list.toArray(new String[list.size()])); // this is where I add the required cipher suites after the SSLSocket is created 
     return socket; 
    } 

    // unchanged wrappers 
    @Override 
    public Socket connectSocket(Socket socket, String s, int i, InetAddress inetAddress, int i1, HttpParams httpParams) throws IOException { return impl.connectSocket(socket, s, i, inetAddress, i1, httpParams); } 

    @Override 
    public boolean isSecure(Socket socket) throws IllegalArgumentException { return impl.isSecure(socket); } 
}; 

schemeRegistry.register(new Scheme("https", sf, 443)); 

// request & execute same as before 

, 그러나 나는 다음과 같은 얻을 수 있기 때문에 호스트 이름의 비교를 깰 것 : 여기

내가 노력 무엇

javax.net.ssl.SSLException: hostname in certificate didn't match: <10.10.10.10> != <sub.example.com> OR <sub.example.com> 

IP 주소가 올바른지 이 호스트. 아마도 내 모든 재정의/래퍼 때문에 원래 https://sub.example.com/ 호스트 이름 대신 url이 전달 된 대신 IP 주소가 사용되는 상황이 발생했을 것입니다.

나를 도와 줄 수 있습니까? 나는 호스트 네스 매칭 문제를 극복하는 방법을 모른다.

답변

0

알 수 있습니다. 아파치 HTTP 클라이언트 라이브러리가 소켓 소켓 sfinstanceof LayeredSocketFactory인지 여부를 확인하고있는 것입니다.이 경우 올바른 SSL/TLS 비교를 위해 10.10.10.10 대신에 대신에 다른 createSocket 메소드가 해당 라이브러리에서 사용됩니다.

따라서 sf은 이와 같이 작성되어야합니다. 추가 createSocket 오버라이드를 확인하십시오.

LayeredSocketFactory sf = new LayeredSocketFactory() { 

    javax.net.ssl.SSLSocketFactory defaultFactory = HttpsURLConnection.getDefaultSSLSocketFactory(); 

    @Override 
    public Socket createSocket(Socket tcpSocket, String host, int port, boolean autoClose) throws IOException { 
     // I'm not actually using impl.createSocket, because then the hostname verifier would have kicked in prior to addMyCipherSuite 
     SSLSocket sslSocket = (SSLSocket) defaultFactory.createSocket(tcpSocket, host, port, autoClose); 
     impl.getHostnameVerifier().verify(host, addMyCipherSuite(sslSocket)); 
     return sslSocket; 
    } 


    @Override 
    public Socket createSocket() throws IOException { 
     return addMyCipherSuite((SSLSocket) impl.createSocket()); 
    } 

    private Socket addMyCipherSuite(SSLSocket socket) { 
     ArrayList<String> list = new ArrayList<>(Arrays.asList(socket.getEnabledCipherSuites())); 
     list.add("SSL_RSA_WITH_RC4_128_SHA"); 
     socket.setEnabledCipherSuites(list.toArray(new String[list.size()])); // this is where I add the required cipher suites after the SSLSocket is created 
     return socket; 
    } 

    // unchanged wrappers 
    @Override 
    public Socket connectSocket(Socket socket, String s, int i, InetAddress inetAddress, int i1, HttpParams httpParams) throws IOException { return impl.connectSocket(socket, s, i, inetAddress, i1, httpParams); } 

    @Override 
    public boolean isSecure(Socket socket) throws IllegalArgumentException { return impl.isSecure(socket); } 
}; 
관련 문제