Merge pull request #94 from RockyTV/caps

Add support for SASLv3.1 PLAIN authentication
This commit is contained in:
Drew DeVault 2017-12-21 06:19:52 -05:00 committed by GitHub
commit 0ec65c919a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 75 additions and 2 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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;
}
}
}
}

View File

@ -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)

View File

@ -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();
}