/// <inheritdoc /> public void Execute(XmppBase xmpp, Tag tag = null) { Features features; xmpp.ClientSocket.SetReadClear(); Logger.Log(LogLevel.Debug, "Starting to parse features"); switch (tag) { case Stream s when s.Version.StartsWith("1."): features = s.Features; break; case Features f: features = f; break; default: Logger.Log(LogLevel.Error, "Unexpected tag. Wrong state executed"); return; } if (features.StartTls != null && (xmpp.UseSsl || features.FeatureCount == 1 || features.StartTls.Required)) { Logger.Log(LogLevel.Debug, "SSL/TLS is required or it is supported and we want to use it"); xmpp.State = new StartTlsState(); xmpp.State.Execute(xmpp); return; } if (xmpp is XmppClient client && !client.Authenticated) { Logger.Log(LogLevel.Debug, "Starting authentication"); client.SaslProcessor = SaslProcessor.CreateProcessor( features.Mechanisms.SupportedTypes, MechanismTypes.Default, client); if (client.SaslProcessor is null) { client.State = new DisconnectState(); client.State.Execute(client); return; } client.ClientSocket.Send(client.SaslProcessor.Initialize(client.Id, client.Password)); client.State = new SaslState(); } }
/// <summary> /// Authenticate a user with the server /// </summary> /// <param name="features">Current <see cref="Features"/> from the server</param> /// <param name="client">Current <see cref="XmppClient"/> instance</param> public static void AuthenticateUser(this Features features, XmppClient client) { client.SaslProcessor = SaslProcessor.CreateProcessor( features.Mechanisms.SupportedTypes, MechanismTypes.Default, client); if (client.SaslProcessor is null) { client.State = new DisconnectState(); client.State.Execute(client); return; } client.ClientSocket.Send(client.SaslProcessor.Initialize(client.Id, client.Password)); client.State = new SaslState(); }
/// <summary> /// </summary> /// <param name="data"> /// A <see cref="Tag" /> /// </param> public override void Execute(Tag data = null) { Features f; if (data is Stream) { var s = data as Stream; if (!s.Version.StartsWith("1.")) { ProtocolState.Events.Error(this, ErrorType.WrongProtocolVersion, ErrorSeverity.Fatal, "Didn't receive expected stream:features tag from 1.x compliant server."); return; } f = s.Features; } else { f = data as Features; } if (f != null) { if (f.StartTls != null && ProtocolState.Settings.Ssl) { ProtocolState.State = new StartTlsState(); var tls = TagRegistry.GetTag <StartTls>("starttls", Namespaces.StartTls); ProtocolState.Socket.Write(tls); return; } if (!ProtocolState.Authenticated) { ProtocolState.Processor = SaslProcessor.CreateProcessor(f.StartSasl.SupportedTypes, ProtocolState.Settings.AuthenticationTypes); if (ProtocolState.Processor == null) { ProtocolState.State = new DisconnectState(); ProtocolState.State.Execute(); return; } ProtocolState.Socket.Write(ProtocolState.Processor.Initialize(ProtocolState.Settings.Id, ProtocolState.Settings.Password)); ProtocolState.State = new SaslState(); return; } // Takes place after authentication according to XEP-0170 if (!ProtocolState.Compressed && CompressionRegistry.AlgorithmsAvailable && !ProtocolState.Settings.Ssl && f.Compression != null) { // Do we have a stream for any of the compressions supported by the server? foreach (string algorithm in f.Compression.Algorithms.Where(CompressionRegistry.SupportsAlgorithm)) { var c = TagRegistry.GetTag <GenericTag>("compress", Namespaces.CompressionProtocol); var m = TagRegistry.GetTag <GenericTag>("method", Namespaces.CompressionProtocol); m.InnerText = ProtocolState.Algorithm = algorithm; c.AddChildTag(m); ProtocolState.Socket.Write(c); ProtocolState.State = new CompressedState(); return; } } } ProtocolState.State = new BindingState(); ProtocolState.State.Execute(); }
/// <summary> /// </summary> /// <param name="data"> /// A <see cref="Tag" /> /// </param> public void Execute(Tag data = null) { Features features; var stream = data as Stream; if (stream != null) { var s = stream; if (!s.Version.StartsWith("1.")) { ProtocolState.Events.Error(this, ErrorType.WrongProtocolVersion, ErrorSeverity.Fatal, "Didn't receive expected stream:features tag from 1.x compliant server."); return; } features = s.Features; } else { features = data as Features; } if (features != null) { // We have features available so make sure we have them set features.Update(); // Should we use SSL and is it required if ((ProtocolState.Features.HasFlag(ProtocolFeatures.StartTls) && ProtocolState.Settings.Ssl) || (ProtocolState.Features.HasFlag(ProtocolFeatures.StartTls) && ProtocolState.Features.HasFlag(ProtocolFeatures.SslRequired)) && !ProtocolState.Encrypted) { Log.Debug("Starting SSL..."); ProtocolState.State = new StartTlsState(); var tls = TagRegistry.GetTag <StartTls>("starttls", Namespaces.StartTls); ProtocolState.Socket.Write(tls); return; } if (!ProtocolState.Authenticated) { Log.Debug("Starting Authentication..."); ProtocolState.Processor = SaslProcessor.CreateProcessor(features.StartSasl.SupportedTypes, ProtocolState.Settings.AuthenticationTypes); if (ProtocolState.Processor == null) { ProtocolState.State = new DisconnectState(); ProtocolState.State.Execute(); return; } ProtocolState.Socket.Write( ProtocolState.Processor.Initialize(ProtocolState.Settings.Id, ProtocolState.Settings.Password)); ProtocolState.State = new SaslState(); return; } // Takes place after authentication according to XEP-0170 if (!ProtocolState.Compressed && CompressionRegistry.AlgorithmsAvailable && !ProtocolState.Settings.Ssl && features.Compression != null) { Log.Debug("Starting Compression..."); // Do we have a stream for any of the compressions supported by the server? foreach (var algorithm in features.Compression.Algorithms.Where(CompressionRegistry.SupportsAlgorithm)) { var c = TagRegistry.GetTag <GenericTag>("compress", Namespaces.CompressionProtocol); var m = TagRegistry.GetTag <GenericTag>("method", Namespaces.CompressionProtocol); m.InnerText = ProtocolState.Algorithm = algorithm; c.AddChildTag(m); ProtocolState.Socket.Write(c); ProtocolState.State = new CompressedState(); return; } } if (ProtocolState.Authenticated) { Log.Debug("Switching to Binding state"); ProtocolState.State = new BindingState(); ProtocolState.State.Execute(); } } }