76 lines
2.3 KiB
C#
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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|