//--------------------------------------------------------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; }
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. }
//--------------------------------------------------------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); }
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()}'."); } }
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); }
//--------------------------------------------------------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; }
//--------------------------------------------------------Constructor:----------------------------------------------------------------\\ #region --Constructors-- /// <summary> /// Basic Constructor /// </summary> /// <history> /// 17/08/2017 Created [Fabian Sauter] /// </history> public AbstractConnectionHandler(XMPPAccount account) { ACCOUNT = account; state = ConnectionState.DISCONNECTED; }