When using Smack 4.1.0 API as XMPP client for Gogles GCM CCS SecurityMode.required does not work

I'm running a Java server that uses the Smack 4.1.0 API as an XMPP client to connect to a Cloud Cloud Server (GCM CCS) server to send messages to an android app. I started with this example ( https://developer.android.com/google/gcm/ccs.html ), but as the Smack API changed, I adapted the code accordingly. So far my Smack Client successfully connects to CCS GCM, sends messages and receives ack / nack / control responses.

Unfortunately the connection only works correctly if I specify XMPPTCPConnectionConfiguration.Builder.setSecurityMode (SecurityMode.ifpossible) or (SecurityMode.disabled). When done, XMPPTCPConnection.isSecureConnection () returns false. See the (relevant) code below:

    static final String GCM_SERVER = "gcm.googleapis.com";
    static final int GCM_PORT = 5235;
    private XMPPTCPConnection connection;
    private SSLContext sslCtx;

    ...

    try {
        KeyStore windowsRootTruststore = KeyStore.getInstance("Windows-ROOT", "SunMSCAPI");
        windowsRootTruststore.load(null, null);
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(windowsRootTruststore);
        sslCtx = SSLContext.getInstance("TLS");
        sslCtx.init(null, tmf.getTrustManagers(), null);
    } catch (KeyStoreException | NoSuchProviderException | NoSuchAlgorithmException
            | KeyManagementException | CertificateException e) {
        e.printStackTrace();
    }

    ...

    XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
        .setHost(GCM_SERVER)
        .setPort(GCM_PORT)
        .setServiceName(GCM_SERVER)
        .setUsernameAndPassword(GCM_SENDER_ID + "@gcm.googleapis.com", GCM_PASSWORD)
        .setCompressionEnabled(false)
        .setSecurityMode(SecurityMode.ifpossible)
        .setSendPresence(false)
        .setSocketFactory(sslCtx.getSocketFactory())
        .build();
    connection = new XMPPTCPConnection(config);
    Roster roster = Roster.getInstanceFor(connection);
    roster.setRosterLoadedAtLogin(false);
    connection.addConnectionListener(this);
    connection.addAsyncStanzaListener(this, new StanzaTypeFilter(Message.class));
    connection.addPacketInterceptor(new StanzaListener() {
            @Override
            public void processPacket(Stanza packet) throws NotConnectedException {
                System.out.println("CCS_Client sent the following message: " + packet.toXML());
            }
        }, new StanzaTypeFilter(Message.class));
    connection.connect();
    connection.login();
    System.out.println(connection.isSecureConnection());

      

According to Google "The connection has two important requirements: 1) You must initiate a Transport Layer Security (TLS) connection ...." (see link above). This sounds to me like a non-TLS encrypted connection will be refused. My problem comes into play with SecurityMode.required. When using Smack, it gives the following error code:

org.jivesoftware.smack.SmackException$SecurityRequiredByClientException: SSL/TLS required by client but not supported by server 
    at org.jivesoftware.smack.tcp.XMPPTCPConnection.afterFeaturesReceived(XMPPTCPConnection.java:898) 
    at org.jivesoftware.smack.AbstractXMPPConnection.parseFeatures(AbstractXMPPConnection.java:1367) 
    at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$800(XMPPTCPConnection.java:139)
    at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:998) 
    at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$200(XMPPTCPConnection.java:937) 
    at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:952) 
    at java.lang.Thread.run(Thread.java:744)

      

I have been trying for two days to figure out why I cannot establish a SecurityMode.required connection, but failed.

Using the same SSLContext / SSLSocketFactory as above, it works great if I connect to GCM CCS without the Smack API, just opening an encrypted TLS connection. As per Googles' note above, when passing a regular SocketFactory (not SSLSocketFactory) to an XMPPTCPConnectionConfiguration, the connection cannot be established:

org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout

      

So my guess is (correct me if I'm wrong) that GCM CCS really only accepts TLS connections. But if so, why is my SecurityMode.required connection attempt rejected using "SSL / TLS required by the client but not supported by the server"?

I'm also wondering if SecurityMode.disabled / SecurityMode.ifpossible actually establishes a TLS connection, but isSecureConnection () returns false, nonetheless? Is this even possible? To test this hypothesis, I wanted to test the underlying SSLsocket that was created in Smack (with SSLSocket.getSession (). GetCipherSuite () and getProtocol () after the handshake completed). To do this, I was trying to pass a custom SSLSocketFactory that creates a custom SSLSocket (which just outputs the CipherSuite and Protocol after the Handshake is complete) to the XMPPTCPConnectionConfiguration. But I don't seem to work either.

How do I get a GCM CCS connection with SecurityMode.required established, for which isSecureConnection () returns true?

Any help would be appreciated!

+3


source to share


2 answers


Same question here that I wound up regarding this error:

https://groups.google.com/forum/#!topic/android-gcm/5mA7FImpTGo

Which means something is wrong in the SSL session cache (disabled by google). I have no luck turning it off on the server side (on my side).

On the other hand, you can see something like this:



org.jivesoftware.smack.roster.Roster     : Exception reloading roster
org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout. Timeout was 5000ms (~5s).

      

If so, you can see it here: https://jira.spring.io/browse/INT-3972

My workaround for now: https://github.com/puel/training/blob/master/gcm/gcm-server/src/main/java/org/sterl/gcm/_example/server/config/GcmConfig.java

0


source


I had the same problem with Smack 4.1.6.



  • SecurityMode

    should not be installed at required

    ( https://community.igniterealtime.org/thread/55808 ).

  • When creating the username, you must use the project NUMBER and not the project ID (can be found at https://console.cloud.google.com ).

  • My stupid mistake, but still. When creating an API key for your project, choose your platform carefully: For some mysterious reason, Android API keys do not work for a simple Java application (lol).

  • It seems the service name can be anything, just not null.

0


source







All Articles