Innovenergy_trunk/csharp/lib/Protocols/DBus/Transport/AuthenticationMethod.cs

76 lines
2.3 KiB
C#

using System.Net.Sockets;
using System.Text;
namespace InnovEnergy.Lib.Protocols.DBus.Transport;
public class AuthenticationMethod
{
public static AuthenticationMethod Anonymous = new AuthenticationMethod(AuthenticateAnonymous);
public static AuthenticationMethod External(UInt16 userId) => new AuthenticationMethod(s => AuthenticateExternal(s, userId));
public static AuthenticationMethod External() => new AuthenticationMethod(s => AuthenticateExternal(s, Env.UserId));
public static AuthenticationMethod ExternalAsRoot() => new AuthenticationMethod(s => AuthenticateExternal(s, 0));
// TODO: other auth modes
public Func<Socket, Guid> Authenticate { get; }
private AuthenticationMethod(Func<Socket, Guid> authenticate)
{
Authenticate = authenticate;
}
private static Guid AuthenticateExternal(Socket socket, UInt16 userId)
{
var user = String
.Concat(Encoding.ASCII.GetBytes(userId.ToString())
.Select(c => c.ToString("X2")));
return AuthenticateAsClient(socket, $"AUTH EXTERNAL {user}");
}
private static Guid AuthenticateAnonymous(Socket s)
{
return AuthenticateAsClient(s, "AUTH ANONYMOUS");
}
private static Guid AuthenticateAsClient(Socket socket, String authCommand)
{
socket.Send(new Byte[] { 0 }, SocketFlags.None);
SendLine(authCommand);
var reply = ReceiveLine();
if (reply is null)
throw new Exception("Connection failure. Connection closed.");
var args = reply.Trim().Split(' ');
if (args[0] != "OK")
throw new Exception("Authentication failure");
SendLine("BEGIN");
return args[1] != String.Empty
? Guid.ParseExact(args[1], "N")
: Guid.Empty;
String? ReceiveLine()
{
using var stream = new NetworkStream(socket);
using var reader = new StreamReader(stream, Encoding.ASCII);
return reader.ReadLine();
}
void SendLine(String line)
{
using var stream = new NetworkStream(socket);
using var writer = new StreamWriter(stream, Encoding.ASCII) { NewLine = "\r\n" };
writer.WriteLine(line);
}
}
}