Search in sources :

Example 1 with SmackDaneVerifier

use of org.jivesoftware.smack.util.dns.SmackDaneVerifier in project Smack by igniterealtime.

the class XMPPTCPConnection method proceedTLSReceived.

/**
     * The server has indicated that TLS negotiation can start. We now need to secure the
     * existing plain connection and perform a handshake. This method won't return until the
     * connection has finished the handshake or an error occurred while securing the connection.
     * @throws IOException 
     * @throws CertificateException 
     * @throws NoSuchAlgorithmException 
     * @throws NoSuchProviderException 
     * @throws KeyStoreException 
     * @throws UnrecoverableKeyException 
     * @throws KeyManagementException 
     * @throws SmackException 
     * @throws Exception if an exception occurs.
     */
@SuppressWarnings("LiteralClassName")
private void proceedTLSReceived() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, NoSuchProviderException, UnrecoverableKeyException, KeyManagementException, SmackException {
    SSLContext context = this.config.getCustomSSLContext();
    KeyStore ks = null;
    KeyManager[] kms = null;
    PasswordCallback pcb = null;
    SmackDaneVerifier daneVerifier = null;
    if (config.getDnssecMode() == DnssecMode.needsDnssecAndDane) {
        SmackDaneProvider daneProvider = DNSUtil.getDaneProvider();
        if (daneProvider == null) {
            throw new UnsupportedOperationException("DANE enabled but no SmackDaneProvider configured");
        }
        daneVerifier = daneProvider.newInstance();
        if (daneVerifier == null) {
            throw new IllegalStateException("DANE requested but DANE provider did not return a DANE verifier");
        }
    }
    if (context == null) {
        final String keyStoreType = config.getKeystoreType();
        final CallbackHandler callbackHandler = config.getCallbackHandler();
        final String keystorePath = config.getKeystorePath();
        if ("PKCS11".equals(keyStoreType)) {
            try {
                Constructor<?> c = Class.forName("sun.security.pkcs11.SunPKCS11").getConstructor(InputStream.class);
                String pkcs11Config = "name = SmartCard\nlibrary = " + config.getPKCS11Library();
                ByteArrayInputStream config = new ByteArrayInputStream(pkcs11Config.getBytes(StringUtils.UTF8));
                Provider p = (Provider) c.newInstance(config);
                Security.addProvider(p);
                ks = KeyStore.getInstance("PKCS11", p);
                pcb = new PasswordCallback("PKCS11 Password: ", false);
                callbackHandler.handle(new Callback[] { pcb });
                ks.load(null, pcb.getPassword());
            } catch (Exception e) {
                LOGGER.log(Level.WARNING, "Exception", e);
                ks = null;
            }
        } else if ("Apple".equals(keyStoreType)) {
            ks = KeyStore.getInstance("KeychainStore", "Apple");
            ks.load(null, null);
        //pcb = new PasswordCallback("Apple Keychain",false);
        //pcb.setPassword(null);
        } else if (keyStoreType != null) {
            ks = KeyStore.getInstance(keyStoreType);
            if (callbackHandler != null && StringUtils.isNotEmpty(keystorePath)) {
                try {
                    pcb = new PasswordCallback("Keystore Password: ", false);
                    callbackHandler.handle(new Callback[] { pcb });
                    ks.load(new FileInputStream(keystorePath), pcb.getPassword());
                } catch (Exception e) {
                    LOGGER.log(Level.WARNING, "Exception", e);
                    ks = null;
                }
            } else {
                ks.load(null, null);
            }
        }
        if (ks != null) {
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            try {
                if (pcb == null) {
                    kmf.init(ks, null);
                } else {
                    kmf.init(ks, pcb.getPassword());
                    pcb.clearPassword();
                }
                kms = kmf.getKeyManagers();
            } catch (NullPointerException npe) {
                LOGGER.log(Level.WARNING, "NullPointerException", npe);
            }
        }
        // If the user didn't specify a SSLContext, use the default one
        context = SSLContext.getInstance("TLS");
        final SecureRandom secureRandom = new java.security.SecureRandom();
        X509TrustManager customTrustManager = config.getCustomX509TrustManager();
        if (daneVerifier != null) {
            // User requested DANE verification.
            daneVerifier.init(context, kms, customTrustManager, secureRandom);
        } else {
            TrustManager[] customTrustManagers = null;
            if (customTrustManager != null) {
                customTrustManagers = new TrustManager[] { customTrustManager };
            }
            context.init(kms, customTrustManagers, secureRandom);
        }
    }
    Socket plain = socket;
    // Secure the plain connection
    socket = context.getSocketFactory().createSocket(plain, host, plain.getPort(), true);
    final SSLSocket sslSocket = (SSLSocket) socket;
    // Immediately set the enabled SSL protocols and ciphers. See SMACK-712 why this is
    // important (at least on certain platforms) and it seems to be a good idea anyways to
    // prevent an accidental implicit handshake.
    TLSUtils.setEnabledProtocolsAndCiphers(sslSocket, config.getEnabledSSLProtocols(), config.getEnabledSSLCiphers());
    // Initialize the reader and writer with the new secured version
    initReaderAndWriter();
    // Proceed to do the handshake
    sslSocket.startHandshake();
    if (daneVerifier != null) {
        daneVerifier.finish(sslSocket);
    }
    final HostnameVerifier verifier = getConfiguration().getHostnameVerifier();
    if (verifier == null) {
        throw new IllegalStateException("No HostnameVerifier set. Use connectionConfiguration.setHostnameVerifier() to configure.");
    } else if (!verifier.verify(getXMPPServiceDomain().toString(), sslSocket.getSession())) {
        throw new CertificateException("Hostname verification of certificate failed. Certificate does not authenticate " + getXMPPServiceDomain());
    }
    // Set that TLS was successful
    secureSocket = sslSocket;
}
Also used : CallbackHandler(javax.security.auth.callback.CallbackHandler) SSLSocket(javax.net.ssl.SSLSocket) SmackDaneProvider(org.jivesoftware.smack.util.dns.SmackDaneProvider) CertificateException(java.security.cert.CertificateException) PasswordCallback(javax.security.auth.callback.PasswordCallback) KeyManager(javax.net.ssl.KeyManager) SmackDaneVerifier(org.jivesoftware.smack.util.dns.SmackDaneVerifier) SecureRandom(java.security.SecureRandom) SSLContext(javax.net.ssl.SSLContext) KeyStore(java.security.KeyStore) KeyStoreException(java.security.KeyStoreException) KeyManagementException(java.security.KeyManagementException) FailedNonzaException(org.jivesoftware.smack.XMPPException.FailedNonzaException) XmppStringprepException(org.jxmpp.stringprep.XmppStringprepException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) XMPPException(org.jivesoftware.smack.XMPPException) ConnectionException(org.jivesoftware.smack.SmackException.ConnectionException) NotConnectedException(org.jivesoftware.smack.SmackException.NotConnectedException) StreamErrorException(org.jivesoftware.smack.XMPPException.StreamErrorException) NoResponseException(org.jivesoftware.smack.SmackException.NoResponseException) IOException(java.io.IOException) SmackException(org.jivesoftware.smack.SmackException) StreamManagementException(org.jivesoftware.smack.sm.StreamManagementException) AlreadyLoggedInException(org.jivesoftware.smack.SmackException.AlreadyLoggedInException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) StreamIdDoesNotMatchException(org.jivesoftware.smack.sm.StreamManagementException.StreamIdDoesNotMatchException) StreamManagementNotEnabledException(org.jivesoftware.smack.sm.StreamManagementException.StreamManagementNotEnabledException) UnrecoverableKeyException(java.security.UnrecoverableKeyException) CertificateException(java.security.cert.CertificateException) SecurityRequiredByServerException(org.jivesoftware.smack.SmackException.SecurityRequiredByServerException) AlreadyConnectedException(org.jivesoftware.smack.SmackException.AlreadyConnectedException) NoSuchProviderException(java.security.NoSuchProviderException) FileInputStream(java.io.FileInputStream) SmackDaneProvider(org.jivesoftware.smack.util.dns.SmackDaneProvider) Provider(java.security.Provider) KeyManagerFactory(javax.net.ssl.KeyManagerFactory) X509TrustManager(javax.net.ssl.X509TrustManager) TrustManager(javax.net.ssl.TrustManager) HostnameVerifier(javax.net.ssl.HostnameVerifier) ByteArrayInputStream(java.io.ByteArrayInputStream) X509TrustManager(javax.net.ssl.X509TrustManager) SSLSocket(javax.net.ssl.SSLSocket) Socket(java.net.Socket)

Aggregations

ByteArrayInputStream (java.io.ByteArrayInputStream)1 FileInputStream (java.io.FileInputStream)1 IOException (java.io.IOException)1 Socket (java.net.Socket)1 KeyManagementException (java.security.KeyManagementException)1 KeyStore (java.security.KeyStore)1 KeyStoreException (java.security.KeyStoreException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 NoSuchProviderException (java.security.NoSuchProviderException)1 Provider (java.security.Provider)1 SecureRandom (java.security.SecureRandom)1 UnrecoverableKeyException (java.security.UnrecoverableKeyException)1 CertificateException (java.security.cert.CertificateException)1 HostnameVerifier (javax.net.ssl.HostnameVerifier)1 KeyManager (javax.net.ssl.KeyManager)1 KeyManagerFactory (javax.net.ssl.KeyManagerFactory)1 SSLContext (javax.net.ssl.SSLContext)1 SSLSocket (javax.net.ssl.SSLSocket)1 TrustManager (javax.net.ssl.TrustManager)1 X509TrustManager (javax.net.ssl.X509TrustManager)1