FileDocCategorySizeDatePackage
SSLCertificateSocketFactory.javaAPI DocAndroid 1.5 API10672Wed May 06 22:41:54 BST 2009android.net

SSLCertificateSocketFactory

public class SSLCertificateSocketFactory extends SSLSocketFactory
SSLSocketFactory that provides optional (on debug devices, only) skipping of ssl certificfate chain validation and custom read timeouts used just when connecting to the server/negotiating an ssl session. You can skip the ssl certificate checking at runtime by setting socket.relaxsslcheck=yes on devices that do not have have ro.secure set.

Fields Summary
private static final String
LOG_TAG
private static X509TrustManager
sDefaultTrustManager
private static final TrustManager[]
TRUST_MANAGER
private final SSLSocketFactory
mFactory
private final int
mSocketReadTimeoutForSslHandshake
Constructors Summary
public SSLCertificateSocketFactory(int socketReadTimeoutForSslHandshake)
Do not use this constructor (will be deprecated). Use {@link #getDefault(int)} instead.


                      
      
               
        this(socketReadTimeoutForSslHandshake, null /* cache */);
    
private SSLCertificateSocketFactory(int socketReadTimeoutForSslHandshake, org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache cache)

        SSLContextImpl sslContext = new SSLContextImpl();
        sslContext.engineInit(null /* kms */,
            TRUST_MANAGER, new java.security.SecureRandom(),
            cache /* client cache */, null /* server cache */);
        this.mFactory = sslContext.engineGetSocketFactory();
        this.mSocketReadTimeoutForSslHandshake = socketReadTimeoutForSslHandshake;
    
Methods Summary
public java.net.SocketcreateSocket(java.lang.String s, int i, java.net.InetAddress inaddr, int j)

        SSLSocket sslSock = (SSLSocket) mFactory.createSocket(s, i, inaddr, j);

        if (mSocketReadTimeoutForSslHandshake >= 0) {
            sslSock.setSoTimeout(mSocketReadTimeoutForSslHandshake);
        }

        validateSocket(sslSock,s);
        sslSock.setSoTimeout(0);
        
        return sslSock;
    
public java.net.SocketcreateSocket(java.lang.String s, int i)

        SSLSocket sslSock = (SSLSocket) mFactory.createSocket(s, i);

        if (mSocketReadTimeoutForSslHandshake >= 0) {
            sslSock.setSoTimeout(mSocketReadTimeoutForSslHandshake);
        }
        
        validateSocket(sslSock,s);
        sslSock.setSoTimeout(0);

        return sslSock;
    
public java.net.SocketcreateSocket(java.net.Socket socket, java.lang.String s, int i, boolean flag)

        throw new IOException("Cannot validate certification without a hostname");       
    
public java.net.SocketcreateSocket(java.net.InetAddress inaddr, int i, java.net.InetAddress inaddr2, int j)

        throw new IOException("Cannot validate certification without a hostname");       
    
public java.net.SocketcreateSocket(java.net.InetAddress inaddr, int i)

        throw new IOException("Cannot validate certification without a hostname");       
    
public static javax.net.SocketFactorygetDefault(int socketReadTimeoutForSslHandshake)
Returns a new instance of a socket factory using the specified socket read timeout while connecting with the server/negotiating an ssl session.

param
socketReadTimeoutForSslHandshake the socket read timeout used for performing ssl handshake. The socket read timeout is set back to 0 after the handshake.
return
a new SocketFactory, or null on error

        return getDefault(socketReadTimeoutForSslHandshake, null /* cache */);
    
public static javax.net.SocketFactorygetDefault(int socketReadTimeoutForSslHandshake, org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache cache)
Returns a new instance of a socket factory using the specified socket read timeout while connecting with the server/negotiating an ssl session. Persists ssl sessions using the provided {@link SSLClientSessionCache}.

param
socketReadTimeoutForSslHandshake the socket read timeout used for performing ssl handshake. The socket read timeout is set back to 0 after the handshake.
param
cache The {@link SSLClientSessionCache} to use, if any.
return
a new SocketFactory, or null on error
hide

        try {
            return new SSLCertificateSocketFactory(socketReadTimeoutForSslHandshake, cache);
        } catch (NoSuchAlgorithmException e) {
            Log.e(LOG_TAG, 
                    "SSLCertifcateSocketFactory.getDefault" +
                    " NoSuchAlgorithmException " , e);
            return null;
        } catch (KeyManagementException e) {
            Log.e(LOG_TAG, 
                    "SSLCertifcateSocketFactory.getDefault" +
                    " KeyManagementException " , e);
            return null; 
        }
    
public java.lang.String[]getDefaultCipherSuites()

        return mFactory.getSupportedCipherSuites();
    
public java.lang.String[]getSupportedCipherSuites()

        return mFactory.getSupportedCipherSuites();
    
private booleanhasValidCertificateChain(java.security.cert.Certificate[] certs)

        if (sDefaultTrustManager == null) {
            if (Config.LOGD) {
                Log.d(LOG_TAG,"hasValidCertificateChain():" +
                          " null default trust manager!");
            }
            throw new IOException("null default trust manager");
        }

        boolean trusted = (certs != null && (certs.length > 0));

        if (trusted) {
            try {
                // the authtype we pass in doesn't actually matter
                sDefaultTrustManager.checkServerTrusted((X509Certificate[]) certs, "RSA");
            } catch (GeneralSecurityException e) { 
                String exceptionMessage = e != null ? e.getMessage() : "none";
                if (Config.LOGD) {
                    Log.d(LOG_TAG,"hasValidCertificateChain(): sec. exception: "
                         + exceptionMessage);
                }
                trusted = false;
            }
        }

        return trusted;
    
private voidvalidateSocket(javax.net.ssl.SSLSocket sslSock, java.lang.String destHost)

        if (Config.LOGV) {
            Log.v(LOG_TAG,"validateSocket() to host "+destHost);
        }

        String relaxSslCheck = SystemProperties.get("socket.relaxsslcheck");
        String secure = SystemProperties.get("ro.secure");

        // only allow relaxing the ssl check on non-secure builds where the relaxation is
        // specifically requested.
        if ("0".equals(secure) && "yes".equals(relaxSslCheck)) {
            if (Config.LOGD) {
                Log.d(LOG_TAG,"sys prop socket.relaxsslcheck is set," +
                        " ignoring invalid certs");
            }
            return;
        }

        Certificate[] certs = null;
        sslSock.setUseClientMode(true);
        sslSock.startHandshake();
        certs = sslSock.getSession().getPeerCertificates();

        // check that the root certificate in the chain belongs to
        // a CA we trust
        if (certs == null) {
            Log.e(LOG_TAG, 
                    "[SSLCertificateSocketFactory] no trusted root CA");
            throw new IOException("no trusted root CA");
        }

        if (Config.LOGV) {
            Log.v(LOG_TAG,"validateSocket # certs = " +certs.length);
        }

        if (!hasValidCertificateChain(certs)) {
            if (Config.LOGD) {
                Log.d(LOG_TAG,"validateSocket(): certificate untrusted!");
            }
            throw new IOException("Certificate untrusted");
        }

        X509Certificate lastChainCert = (X509Certificate) certs[0];

        if (!DomainNameChecker.match(lastChainCert, destHost)) {
            if (Config.LOGD) {
                Log.d(LOG_TAG,"validateSocket(): domain name check failed");
            }
            throw new IOException("Domain Name check failed");
        }