Add support for SASL PLAIN authentication
This commit is contained in:
parent
64dbcddf43
commit
bfddb78217
|
@ -42,11 +42,19 @@ namespace ChatSharp.Handlers
|
|||
// Get the accepted capabilities
|
||||
var acceptedCaps = message.Parameters[2].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (string acceptedCap in acceptedCaps)
|
||||
{
|
||||
client.Capabilities.Enable(acceptedCap);
|
||||
// Begin SASL authentication
|
||||
if (acceptedCap == "sasl")
|
||||
{
|
||||
client.SendRawMessage("AUTHENTICATE PLAIN");
|
||||
client.IsAuthenticatingSasl = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the enabled capabilities count is the same as the ones
|
||||
// acknowledged by the server.
|
||||
if (client.IsNegotiatingCapabilities && client.Capabilities.Enabled.Count() == acceptedCaps.Count())
|
||||
if (client.IsNegotiatingCapabilities && client.Capabilities.Enabled.Count() == acceptedCaps.Count() && !client.IsAuthenticatingSasl)
|
||||
{
|
||||
client.SendRawMessage("CAP END");
|
||||
client.IsNegotiatingCapabilities = false;
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace ChatSharp.Handlers
|
|||
client.SetHandler("330", UserHandlers.HandleWhoIsLoggedInAs);
|
||||
client.SetHandler("352", UserHandlers.HandleWho);
|
||||
client.SetHandler("354", UserHandlers.HandleWhox);
|
||||
client.SetHandler("900", UserHandlers.HandleLoggedIn); // ERR_LOGGEDIN
|
||||
client.SetHandler("ACCOUNT", UserHandlers.HandleAccount);
|
||||
client.SetHandler("CHGHOST", UserHandlers.HandleChangeHost);
|
||||
|
||||
|
@ -76,6 +77,14 @@ namespace ChatSharp.Handlers
|
|||
|
||||
// Capability handlers
|
||||
client.SetHandler("CAP", CapabilityHandlers.HandleCapability);
|
||||
|
||||
// SASL handlers
|
||||
client.SetHandler("AUTHENTICATE", SaslHandlers.HandleAuthentication);
|
||||
client.SetHandler("903", SaslHandlers.HandleError); // ERR_SASLSUCCESS
|
||||
client.SetHandler("904", SaslHandlers.HandleError); // ERR_SASLFAIL
|
||||
client.SetHandler("905", SaslHandlers.HandleError); // ERR_SASLTOOLONG
|
||||
client.SetHandler("906", SaslHandlers.HandleError); // ERR_SASLABORTED
|
||||
client.SetHandler("907", SaslHandlers.HandleError); // ERR_SASLALREADY
|
||||
}
|
||||
|
||||
public static void HandleNick(IrcClient client, IrcMessage message)
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
|
||||
namespace ChatSharp.Handlers
|
||||
{
|
||||
internal static class SaslHandlers
|
||||
{
|
||||
public static void HandleAuthentication(IrcClient client, IrcMessage message)
|
||||
{
|
||||
if (client.IsAuthenticatingSasl)
|
||||
{
|
||||
if (message.Parameters[0] == "+")
|
||||
{
|
||||
// Based off irc-framework implementation
|
||||
var plainString = string.Format("{0}\0{0}\0{1}", client.User.Nick, client.User.Password);
|
||||
var b64Bytes = Encoding.UTF8.GetBytes(Convert.ToBase64String(Encoding.UTF8.GetBytes(plainString)));
|
||||
|
||||
while (b64Bytes.Length >= 400)
|
||||
{
|
||||
var chunk = b64Bytes.Take(400).ToArray();
|
||||
b64Bytes = b64Bytes.Skip(400).ToArray();
|
||||
client.SendRawMessage(string.Format("AUTHENTICATE {0}", Encoding.UTF8.GetString(chunk)));
|
||||
}
|
||||
if (b64Bytes.Length > 0)
|
||||
client.SendRawMessage(string.Format("AUTHENTICATE {0}", Encoding.UTF8.GetString(b64Bytes)));
|
||||
else
|
||||
client.SendRawMessage("AUTHENTICATE +");
|
||||
|
||||
client.IsAuthenticatingSasl = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void HandleError(IrcClient client, IrcMessage message)
|
||||
{
|
||||
if (client.IsNegotiatingCapabilities && !client.IsAuthenticatingSasl)
|
||||
{
|
||||
client.SendRawMessage("CAP END");
|
||||
client.IsNegotiatingCapabilities = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -217,6 +217,11 @@ namespace ChatSharp.Handlers
|
|||
}
|
||||
}
|
||||
|
||||
public static void HandleLoggedIn(IrcClient client, IrcMessage message)
|
||||
{
|
||||
client.User.Account = message.Parameters[2];
|
||||
}
|
||||
|
||||
public static void HandleWhoEnd(IrcClient client, IrcMessage message)
|
||||
{
|
||||
if (client.ServerInfo.ExtendedWho)
|
||||
|
|
|
@ -138,6 +138,11 @@ namespace ChatSharp
|
|||
/// If set to False, capability negotiation is finished.
|
||||
/// </summary>
|
||||
public bool IsNegotiatingCapabilities { get; internal set; }
|
||||
/// <summary>
|
||||
/// Set to True when the client is authenticating with SASL.
|
||||
/// If set to False, SASL authentication is finished.
|
||||
/// </summary>
|
||||
public bool IsAuthenticatingSasl { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IRC client, but will not connect until ConnectAsync is called.
|
||||
|
@ -169,10 +174,11 @@ namespace ChatSharp
|
|||
// List of supported capabilities
|
||||
Capabilities.AddRange(new string[] {
|
||||
"server-time", "multi-prefix", "cap-notify", "znc.in/server-time", "znc.in/server-time-iso",
|
||||
"account-notify", "chghost", "userhost-in-names"
|
||||
"account-notify", "chghost", "userhost-in-names", "sasl"
|
||||
});
|
||||
|
||||
IsNegotiatingCapabilities = false;
|
||||
IsAuthenticatingSasl = false;
|
||||
|
||||
RandomNumber = new Random();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue