protected override async Task processMessageAsync(NewValidMessageEventArgs args) { if (!STREAM_MANAGEMENT_ENABLED) { return; } AbstractMessage msg = args.MESSAGE; switch (state) { case SMState.DISABLED: if (msg is StreamFeaturesMessage || msg is OpenStreamAnswerMessage) { StreamFeaturesMessage features = null; if (msg is OpenStreamAnswerMessage) { features = (msg as OpenStreamAnswerMessage).getStreamFeaturesMessage(); } else { features = msg as StreamFeaturesMessage; } if (features is null) { return; } if (features.containsFeature("sm")) { setMessageProcessed(args); SMEnableMessage enableMsg = new SMEnableMessage(); await XMPP_CONNECTION.sendAsync(enableMsg, true); serverSMEnabled = true; state = SMState.REQUESTED; } } break; case SMState.REQUESTED: if (msg is SMEnableMessage enableAnswMsg) { setMessageProcessed(args); // Update connection information: state = SMState.ENABLED; clientSMEnabled = true; stopListeningForMessages(); } else if (msg is SMFailedMessage failedMsg) { setMessageProcessed(args); // Handle errors: state = SMState.ERROR; stopListeningForMessages(); } break; } }
public void onSaslError(string errMsg, SASLState newState) { Task.Run(async() => { Logger.Error(errMsg); await XMPP_CONNECTION.OnMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.SASL_FAILED, errMsg), true); state = newState; }); }
protected async override Task processMessageAsync(NewValidMessageEventArgs args) { AbstractMessage msg = args.MESSAGE; if (state == RecourceBindingState.BOUND || state == RecourceBindingState.ERROR || msg.isProcessed()) { return; } switch (state) { case RecourceBindingState.UNBOUND: if (msg is StreamFeaturesMessage || msg is OpenStreamAnswerMessage) { StreamFeaturesMessage features; if (msg is OpenStreamAnswerMessage) { features = (msg as OpenStreamAnswerMessage).getStreamFeaturesMessage(); } else { features = msg as StreamFeaturesMessage; } if (features is null) { return; } if (features.containsFeature("bind")) { setMessageProcessed(args); BindResourceMessage bindMsg = new BindResourceMessage(XMPP_CONNECTION.account.user.resourcePart); id = bindMsg.ID; await XMPP_CONNECTION.SendAsync(bindMsg, true); state = RecourceBindingState.BINDING; } } break; case RecourceBindingState.BINDING: if (msg is IQMessage) { IQMessage iQM = msg as IQMessage; if (string.Equals(iQM.ID, id)) { stopListeningForMessages(); setMessageProcessed(args); XMPP_CONNECTION.SendAsync(new StartSessionMessage(), true).Wait(); state = RecourceBindingState.BOUND; ResourceBound?.Invoke(this, new EventArgs()); } } break; } }
private async Task streamFeaturesMessageReceivedAsync(StreamFeaturesMessage features, NewValidMessageEventArgs args) { TLSStreamFeature tlsFeature = getTLSStreamFeature(features); TLSConnectionMode connectionMode = TCP_CONNECTION.account.connectionConfiguration.tlsMode; if (tlsFeature != null) { if (connectionMode == TLSConnectionMode.PROHIBIT) { if (tlsFeature.REQUIRED) { stopListeningForMessages(); string errorMsg = "TSL is required for server but TLS connection mode is set to prohibit!"; Logger.Error(errorMsg); setState(TLSState.ERROR); await XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.TLS_CONNECTION_FAILED, errorMsg), true); } else { setState(TLSState.PROHIBITED); } return; } // Starting the TSL process: setMessageProcessed(args); setState(TLSState.CONNECTING); await XMPP_CONNECTION.sendAsync(new RequesStartTLSMessage(), false, true); setState(TLSState.REQUESTED); } else { if (connectionMode == TLSConnectionMode.FORCE) { stopListeningForMessages(); string errorMsg = "TSL is not available for this server but TLS connection mode is set to force!"; Logger.Error(errorMsg); setState(TLSState.ERROR); await XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.TLS_CONNECTION_FAILED, errorMsg), true); return; } } }
private void selectMechanism(ArrayList mechanisms) { string selected = null; foreach (string s in OFFERED_MECHANISMS) { foreach (string m in mechanisms) { if (m.ToLower().Equals(s)) { selected = s; break; } } if (selected != null) { break; } } XMPPAccount sCC = XMPP_CONNECTION.account; switch (selected) { case "scram-sha-1": selectedMechanism = new ScramSHA1SASLMechanism(sCC.user.userId, sCC.user.userPassword); break; case "plain": selectedMechanism = new PlainSASLMechanism(sCC.user.userId, sCC.user.userPassword); break; default: state = SASLState.NO_VALID_MECHANISM; Logger.Error("Failed to select authentication mechanism. No supported mechanism available!"); Task t = XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.SASL_FAILED, "Failed to select authentication mechanism. No supported mechanism available!"), true); break; } }
protected async override Task processMessageAsync(NewValidMessageEventArgs args) { AbstractMessage msg = args.MESSAGE; if (msg.isProcessed()) { return; } switch (state) { case SASLState.DISCONNECTED: if (msg is StreamFeaturesMessage || msg is OpenStreamAnswerMessage) { StreamFeaturesMessage features = null; if (msg is OpenStreamAnswerMessage) { features = (msg as OpenStreamAnswerMessage).getStreamFeaturesMessage(); } else { features = msg as StreamFeaturesMessage; } if (features is null) { return; } ArrayList mechanisms = getMechanisms(features); if (mechanisms is null) { return; } setMessageProcessed(args); selectMechanism(mechanisms); if (selectedMechanism is null) { state = SASLState.ERROR; await XMPP_CONNECTION.OnMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.SASL_FAILED, "selectedMechanism is null"), true); return; } await XMPP_CONNECTION.SendAsync(selectedMechanism.getSelectSASLMechanismMessage(), true); state = SASLState.REQUESTED; } break; case SASLState.REQUESTED: case SASLState.CHALLENGING: if (msg is ScramSHAChallengeMessage) { state = SASLState.CHALLENGING; setMessageProcessed(args); AbstractMessage response = selectedMechanism.generateResponse(msg); if (!(response is null)) { await XMPP_CONNECTION.SendAsync(response, true); } } else if (msg is SASLSuccessMessage) { state = SASLState.CONNECTED; msg.setRestartConnection(AbstractMessage.SOFT_RESTART); setMessageProcessed(args); stopListeningForMessages(); } else if (msg is SASLFailureMessage) { stopListeningForMessages(); SASLFailureMessage saslFailureMessage = msg as SASLFailureMessage; state = SASLState.ERROR; Logger.Error("Error during SASL authentication: " + saslFailureMessage.ERROR_TYPE + "\n" + saslFailureMessage.ERROR_MESSAGE); if (saslFailureMessage.ERROR_TYPE == SASLErrorType.UNKNOWN_ERROR) { await XMPP_CONNECTION.OnMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.SASL_FAILED, "SASL: " + saslFailureMessage.ERROR_MESSAGE), true); } else { await XMPP_CONNECTION.OnMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.SASL_FAILED, "SASL: " + saslFailureMessage.ERROR_TYPE), true); } } break; case SASLState.CONNECTED: break; default: throw new InvalidOperationException("Unexpected value for state: " + state); } }
protected async override Task processMessageAsync(NewValidMessageEventArgs args) { AbstractMessage msg = args.MESSAGE; if (msg.isProcessed()) { return; } if ((state == TLSState.CONNECTING || state == TLSState.REQUESTED) && msg is ErrorMessage) { setMessageProcessed(args); setState(TLSState.ERROR); ErrorMessage error = msg as ErrorMessage; if (error.getType().Equals(Consts.XML_FAILURE)) { error.setRestartConnection(AbstractMessage.HARD_RESTART); } return; } switch (state) { case TLSState.DISCONNECTED: case TLSState.CONNECTING: if (msg is OpenStreamAnswerMessage) { StreamFeaturesMessage features = (msg as OpenStreamAnswerMessage).getStreamFeaturesMessage(); if (features != null) { await streamFeaturesMessageReceivedAsync(features, args); } } else if (msg is StreamFeaturesMessage) { await streamFeaturesMessageReceivedAsync(msg as StreamFeaturesMessage, args); } break; case TLSState.REQUESTED: if (msg is ProceedAnswerMessage) { setMessageProcessed(args); XMPPAccount account = XMPP_CONNECTION.account; Logger.Debug("Upgrading " + account.getBareJid() + " connection to TLS..."); try { TCP_CONNECTION.upgradeToTLSAsync().Wait(); } catch (AggregateException e) { if (e.InnerException is TaskCanceledException) { Logger.Error("Timeout during upgrading " + account.getBareJid() + " to TLS!", e); setState(TLSState.ERROR); await XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.TLS_CONNECTION_FAILED, "TSL upgrading timeout!"), true); return; } else { Logger.Error("Error during upgrading " + account.getBareJid() + " to TLS!", e.InnerException); setState(TLSState.ERROR); await XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.TLS_CONNECTION_FAILED, e.InnerException?.Message), true); return; } } catch (Exception e) { Logger.Error("Error during upgrading " + account.getBareJid() + " to TLS!", e); setState(TLSState.ERROR); await XMPP_CONNECTION.onMessageProcessorFailedAsync(new ConnectionError(ConnectionErrorCode.TLS_CONNECTION_FAILED, e.Message), true); return; } Logger.Debug("Success upgrading " + account.getBareJid() + " to TLS."); setState(TLSState.CONNECTED); stopListeningForMessages(); // TLS established ==> resend stream header msg.setRestartConnection(AbstractMessage.SOFT_RESTART); } break; } }