Example #1
0
        //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
        #region --Constructors--
        public XmppConnection(XMPPAccount account) : base(account)
        {
            TCP_CONNECTION = new TcpConnection(account);
            TCP_CONNECTION.ConnectionStateChanged += TcpConnection_ConnectionStateChanged;
            TCP_CONNECTION.NewDataReceived        += TCP_CONNECTION_NewDataReceived;

            GENERAL_COMMAND_HELPER = new GeneralCommandHelper(this);
            MUC_COMMAND_HELPER     = new MUCCommandHelper(this);
            PUB_SUB_COMMAND_HELPER = new PubSubCommandHelper(this);
            OMEMO_COMMAND_HELPER   = new OmemoCommandHelper(this);
            DISCO_HELPER           = new DiscoFeatureHelper(this);

            // The order in which new messages should get processed (TLS -- SASL -- Stream Management -- Resource binding -- ...).
            // https://xmpp.org/extensions/xep-0170.html
            //-------------------------------------------------------------
            // TLS:
            MESSAGE_PROCESSORS[0] = new TLSConnection(TCP_CONNECTION, this);

            // SASL:
            MESSAGE_PROCESSORS[1] = new SASLConnection(TCP_CONNECTION, this);

            // XEP-0198 (Stream Management):
            MESSAGE_PROCESSORS[2] = new SMConnection(TCP_CONNECTION, this);

            // Resource binding:
            RecourceBindingConnection recourceBindingConnection = new RecourceBindingConnection(TCP_CONNECTION, this);

            recourceBindingConnection.ResourceBound += RecourceBindingConnection_ResourceBound;
            MESSAGE_PROCESSORS[3] = recourceBindingConnection;
            //-------------------------------------------------------------

            NetworkHelper.Instance.NetworkChanged += Instance_NetworkChanged;
        }
Example #2
0
        public async Task decryptOmemoEncryptedMessageAsync(OmemoEncryptedMessage msg, bool trustedKeysOnly)
        {
            XMPPAccount          account         = CONNECTION.account;
            OmemoProtocolAddress receiverAddress = new OmemoProtocolAddress(account.getBareJid(), account.omemoDeviceId);
            // Try to decrypt the message, in case no exception occurred, everything went fine:
            OmemoDecryptionContext decryptCtx = new OmemoDecryptionContext(receiverAddress, account.omemoIdentityKey, account.omemoSignedPreKey, account.OMEMO_PRE_KEYS, trustedKeysOnly, OMEMO_STORAGE);

            msg.decrypt(decryptCtx);
            Debug.Assert(!msg.ENCRYPTED);
            Logger.Debug("Successfully decrypted an " + nameof(OmemoEncryptedMessage) + " for '" + receiverAddress.BARE_JID + "'.");

            // Republish bundle information in case the message is a key exchange message and used a PreKey:
            if (decryptCtx.keyExchange)
            {
                Logger.Info("Received a OMEMO key exchange message. Republishing bundle for '" + receiverAddress.BARE_JID + "'...");
                PreKeyModel newPreKey = decryptCtx.STORAGE.ReplaceOmemoPreKey(decryptCtx.usedPreKey);
                account.OMEMO_PRE_KEYS.Remove(decryptCtx.usedPreKey);
                account.OMEMO_PRE_KEYS.Add(newPreKey);
                await announceBundleInfoAsync();

                Logger.Info("Bundle for '" + receiverAddress.BARE_JID + "' republished.");
            }

            // Reply with an empty message to confirm the successful key exchange:
            // TODO: This is no good way, since there it would be possible to stalk people without them knowing.
        }
Example #3
0
        //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
        #region --Constructors--
        /// <summary>
        /// Basic Constructor
        /// </summary>
        /// <history>
        /// 05/05/2018 Created [Fabian Sauter]
        /// </history>
        public XMPPConnection2(XMPPAccount account) : base(account)
        {
            this.holdConnection       = false;
            this.connectionErrorCount = 0;
            this.lastConnectionError  = null;
            this.TCP_CONNECTION       = new TCPConnection2(account);
            this.TCP_CONNECTION.ConnectionStateChanged += TCPConnection_ConnectionStateChanged;
            this.TCP_CONNECTION.NewDataReceived        += TCPConnection_NewDataReceived;

            this.PARSER             = new MessageParser2();
            this.MESSAGE_PROCESSORS = new AbstractMessageProcessor[4];
            this.streamId           = null;
            this.messageIdCache     = new TSTimedList <string>();

            this.connectionTimer    = null;
            this.reconnectRequested = false;
            this.timeout            = TimeSpan.FromMilliseconds(CONNECTION_TIMEOUT);

            this.GENERAL_COMMAND_HELPER = new GeneralCommandHelper(this);
            this.MUC_COMMAND_HELPER     = new MUCCommandHelper(this);
            this.PUB_SUB_COMMAND_HELPER = new PubSubCommandHelper(this);
            this.OMEMO_COMMAND_HELPER   = new OmemoCommandHelper(this);

            // The order in which new messages should get processed (TLS -- SASL -- Stream Management -- Resource binding -- ...).
            // https://xmpp.org/extensions/xep-0170.html
            //-------------------------------------------------------------
            // TLS:
            this.MESSAGE_PROCESSORS[0] = new TLSConnection(TCP_CONNECTION, this);

            // SASL:
            this.MESSAGE_PROCESSORS[1] = new SASLConnection(TCP_CONNECTION, this);

            // XEP-0198 (Stream Management):
            this.MESSAGE_PROCESSORS[2] = new SMConnection(TCP_CONNECTION, this);

            // Resource binding:
            RecourceBindingConnection recourceBindingConnection = new RecourceBindingConnection(TCP_CONNECTION, this);

            recourceBindingConnection.ResourceBound += RecourceBindingConnection_ResourceBound;
            this.MESSAGE_PROCESSORS[3] = recourceBindingConnection;
            //-------------------------------------------------------------

            NetworkHelper.Instance.NetworkChanged += Instance_NetworkChanged;

            this.omemoHelper          = null;
            this.DISCO_FEATURE_HELPER = new DiscoFeatureHelper(this);
        }
Example #4
0
        public async Task decryptOmemoEncryptedMessageAsync(OmemoEncryptedMessage msg, bool trustedKeysOnly)
        {
            XMPPAccount          account         = CONNECTION.account;
            OmemoProtocolAddress receiverAddress = new OmemoProtocolAddress(account.getBareJid(), account.omemoDeviceId);
            // Try to decrypt the message, in case no exception occurred, everything went fine:
            OmemoDecryptionContext decryptCtx = new OmemoDecryptionContext(receiverAddress, account.omemoIdentityKey, account.omemoSignedPreKey, account.OMEMO_PRE_KEYS, trustedKeysOnly, OMEMO_STORAGE);

            msg.decrypt(decryptCtx);
            Debug.Assert(!msg.ENCRYPTED);
            Logger.Debug("Successfully decrypted an " + nameof(OmemoEncryptedMessage) + " for '" + receiverAddress.BARE_JID + "'.");

            // Republish bundle information in case the message is a key exchange message and used a PreKey:
            if (decryptCtx.keyExchange)
            {
                Logger.Info("Received a OMEMO key exchange message. Republishing bundle for '" + receiverAddress.BARE_JID + "'...");
                PreKeyModel newPreKey = decryptCtx.STORAGE.ReplaceOmemoPreKey(decryptCtx.usedPreKey);
                account.OMEMO_PRE_KEYS.Remove(decryptCtx.usedPreKey);
                account.OMEMO_PRE_KEYS.Add(newPreKey);
                await announceBundleInfoAsync();

                Logger.Info("Bundle for '" + receiverAddress.BARE_JID + "' republished.");

                // Reply with an empty message to confirm the successful key exchange:
                // TODO: This is no good way, since there it would be possible to stalk people without them knowing.
                OmemoEncryptedMessage reply       = new OmemoEncryptedMessage(msg.getTo(), msg.getFrom(), null, msg.TYPE, false);
                OmemoDeviceGroup      deviceGroup = new OmemoDeviceGroup(decryptCtx.senderAddress.BARE_JID);
                deviceGroup.SESSIONS.Add(decryptCtx.senderAddress.DEVICE_ID, decryptCtx.session);
                try
                {
                    reply.encrypt(CONNECTION.account.omemoDeviceId, CONNECTION.account.omemoIdentityKey, OMEMO_STORAGE, new List <OmemoDeviceGroup> {
                        deviceGroup
                    });
                    await CONNECTION.SendAsync(reply);
                }
                catch (Exception e)
                {
                    Logger.Error("[OMEMO HELPER] Failed to encrypt and the empty OMEMO message reply with: ", e);
                }
                Logger.Info($"Send an empty OMEMO message to confirm the successful key exchange with '{msg.getFrom()}'.");
            }
        }
Example #5
0
 public override bool Equals(object obj)
 {
     if (obj is XMPPAccount)
     {
         XMPPAccount o = obj as XMPPAccount;
         return(o.disabled == disabled &&
                o.port == port &&
                o.presencePriorety == presencePriorety &&
                string.Equals(o.serverAddress, serverAddress) &&
                Equals(o.user, user) &&
                string.Equals(o.color, color) &&
                o.presence == presence &&
                string.Equals(o.status, status) &&
                connectionConfiguration.Equals(o.connectionConfiguration) &&
                o.omemoDeviceId == omemoDeviceId &&
                Equals(o.omemoIdentityKeyPair.serialize(), omemoIdentityKeyPair.serialize()) &&
                Equals(o.omemoSignedPreKeyPair.serialize(), omemoSignedPreKeyPair.serialize()) &&
                Equals(o.omemoPreKeys, omemoPreKeys) &&
                o.omemoBundleInfoAnnounced == omemoBundleInfoAnnounced);
     }
     return(false);
 }
Example #6
0
 //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
 #region --Constructors--
 /// <summary>
 /// Basic Constructor
 /// </summary>
 /// <history>
 /// 05/05/2018 Created [Fabian Sauter]
 /// </history>
 protected AbstractConnection2(XMPPAccount account)
 {
     this.account = account;
     this.state   = ConnectionState.DISCONNECTED;
 }
 //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
 #region --Constructors--
 protected AbstractConnection(XMPPAccount account)
 {
     this.account = account;
 }
Example #8
0
 //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
 #region --Constructors--
 /// <summary>
 /// Basic Constructor
 /// </summary>
 /// <history>
 /// 17/08/2017 Created [Fabian Sauter]
 /// </history>
 public AbstractConnectionHandler(XMPPAccount account)
 {
     ACCOUNT = account;
     state   = ConnectionState.DISCONNECTED;
 }