carlosCharz / fcmxmppserverv2

XMPP Connection Server for FCM using the latest version of the Smack library (4.3.4) + Connection Draining Implementation
47 stars 33 forks source link

xml parser error #17

Closed dfeng99 closed 6 years ago

dfeng99 commented 6 years ago

Hi,

When connect to FCM server, I got the following exception stack trace when call connect. I've search the error on the internet but didn't find useful information.

org.xmlpull.v1.XmlPullParserException: only whitespace content allowed before start tag and not \u15 (position: START_DOCUMENT seen \u15... @1:1) at org.xmlpull.mxp1.MXParser.parseProlog(MXParser.java:1519) at org.xmlpull.mxp1.MXParser.nextImpl(MXParser.java:1395) at org.xmlpull.mxp1.MXParser.next(MXParser.java:1093) at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1244) at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$300(XMPPTCPConnection.java:994) at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:1010) at java.lang.Thread.run(Thread.java:748)

I've also traced the code at mxParser.parseProlog, it does try to skip some unicodes but \u15.

It seems that FCM response a character \u15 which can't be parsed. I am not sure is it because my wrong configuration or it's a bug?

My Configuration is as below: XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() .setXmppDomain(FcmSettings.FCM_SERVER_CONNECTION) .setHost(FcmSettings.FCM_SERVER) .setPort(FcmSettings.FCM_PORT_DEVELOPMENT) .setSecurityMode(SecurityMode.ifpossible) .addEnabledSaslMechanism("PLAIN") .setEnabledSSLProtocols(enabledSSL) .setConnectTimeout((int) FcmSettings.timeout_milisecond) .setUsernameAndPassword(sasl_auth, FcmSettings.FCM_AuthKey) .setSendPresence(false) .build();

Regards, David

carlosCharz commented 6 years ago

Hi David,

first of all, I don't know either that problem but we can break it down in minor pieces to discard any misconfiguration (the easiest one). Can you try it the same way I have in the project? I updated from the last time and was working.

I do not have these parameters in mine, you can remove those just to test. And like this remove any configuration that is different from the original.

.addEnabledSaslMechanism("PLAIN") .setEnabledSSLProtocols(enabledSSL)

PD: that seems to be a parsing problem but it looks like that the packet arrived like this: \u15. Maybe the source can changed its configuration to send the packet in the proper way?

Let me know if it works. Greetings!

dfeng99 commented 6 years ago

Hi Carlos,

Thanks, your configuration works! 👍 but still don't know why! :-( , I think I just put all settings in one configuration statement.

I also add one line to evaluate the security settings: connection.isSecureConnection() and it return false.

I am curious about that in Firebase "Authorize an XMPP connection" it says

The connection has two important requirements:

and if the connection is not secure, why it still works? I experimentally read the keystore and configure the KeyManager and TrustManager but with no luck, an exception thrown sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target Anyway this is not important, answer it only if you have an idea! Sorry to bother you, I think you probably still in a long holidays!

Many thanks!

carlosCharz commented 6 years ago

Hi David,

I am really glad you solved your problem. Actually it is good that you bring up that issue so I can search more about it. In my ccs connection there is other piece of code regarding the sas plain auth:

// Check SASL authentication logger.info("SASL PLAIN authentication enabled? {}", SASLAuthentication.isSaslMechanismRegistered("PLAIN")); SASLAuthentication.unBlacklistSASLMechanism("PLAIN"); SASLAuthentication.blacklistSASLMechanism("DIGEST-MD5");

Actually it would be useful to find out a better way to secure the app. I was adding stuffs due to community collaboration.

Greetings and merry christmas :)

PD: maybe your "isSecureConnection()" is related to the https or ssl certificates? ...

dfeng99 commented 6 years ago

Hi Carlos,

Merry Christmas :-), yes, I am trying to follow the firebase recommendation to initiate a TLS tunnel but failed, I used keytool to validate the path, and the FileInputStream, KeyManagerFactory, TrustManagerFactory in code all do not report error.

` SSLContext sslContext = SSLContext.getInstance("TLS"); final KeyStore keyStore = KeyStore.getInstance("JKS"); try ( final InputStream is = new FileInputStream( FcmSettings.JAVA_KEYSTORE) ) { keyStore.load(is, JKS_PASSWORD); } catch (CertificateException e1) { e1.printStackTrace(); }

        KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm()
        );
        kmfactory.init(keyStore, KEY_PASSWORD);
        KeyManager[] kms =  kmfactory.getKeyManagers();

        final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory
                .getDefaultAlgorithm());
        tmf.init(keyStore);

// X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; // SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); // TrustManager[] tms = new TrustManager[] {tm};

        TrustManager[] tms = tmf.getTrustManagers();

        SecureRandom random = new SecureRandom();
        sslContext.init(kms, tms, random);`

and smack xmpp configuration .setSocketFactory(sslContext.getSocketFactory()) is added

It fails during Handshaking. I believe it may related to the smack configuration call sequence or the keystore type or cert type.

The full stack trace is follow: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026) at sun.security.ssl.Handshaker.process_record(Handshaker.java:961) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385) at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:938) at sun.security.ssl.AppInputStream.read(AppInputStream.java:105) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.BufferedReader.read1(BufferedReader.java:210) at java.io.BufferedReader.read(BufferedReader.java:286) at org.xmlpull.mxp1.MXParser.fillBuf(MXParser.java:2992) at org.xmlpull.mxp1.MXParser.more(MXParser.java:3046) at org.xmlpull.mxp1.MXParser.parseProlog(MXParser.java:1410) at org.xmlpull.mxp1.MXParser.nextImpl(MXParser.java:1395) at org.xmlpull.mxp1.MXParser.next(MXParser.java:1093) at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1244) at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$300(XMPPTCPConnection.java:994) at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:1010) at java.lang.Thread.run(Thread.java:748)

Regards,

carlosCharz commented 6 years ago

I think that your problem might not be the KeyManagerFactory or TrustManagerFactory but the smack interface for its socket factory. You'd better look for smack's ssl examples first :)

dfeng99 commented 6 years ago

Agree and that's why I am here! :-) . It's hard to find an example for version 4.2.2. Since I am new on smack, maybe I should register an account in smack forum.

Still many thanks for your help and you code help me a lot on understanding smack. Meanwhile, wish that my failed experience can also give you some idea when add TLS support. Well, the current work around is not to use TLS until Firebase force to have it.

As the code I posted previously, If I replace .setSocketFactory(sslContext.getSocketFactory() to .setCustomSSLContext(sslContext) then the error will goes to \u15 parser error. It seems that the tunnel has been successfully setup but something wrong on handling the response (It could also be a bug of smack 4.2.2). Perhaps, to setup the TLS tunnel by native Java library then call smack login could be another work around.

Have a nice day!

Regards,

dfeng99 commented 6 years ago

By the way, I found a useful tools SSLPoke, the PKIX exception is because of the wrong truststore assigend. The default truststore contains all required certificates. So, the issue probably goes to why isSecureConnection() returns false.

carlosCharz commented 6 years ago

@dfeng99 thank you very much for the information and contribution. I wish you the best in the project you are working on!