122 lines
3.7 KiB
C#
122 lines
3.7 KiB
C#
// /**
|
|
// * File: RadiusMessage.cs
|
|
// * Author: haraldwolff
|
|
// *
|
|
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
|
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
|
// *
|
|
// *
|
|
// **/
|
|
using System;
|
|
using System.Net;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using ln.types;
|
|
using System.Security.Cryptography;
|
|
namespace ln.radius
|
|
{
|
|
public enum RadiusCode : byte {
|
|
AccessRequest = 1,
|
|
AccessAccept = 2,
|
|
AccessReject = 3,
|
|
AccountingRequest = 4,
|
|
AccountingResponse = 5,
|
|
AccessChallenge = 11,
|
|
StatusServer = 12,
|
|
StatusClient = 13,
|
|
Reserved = 255
|
|
}
|
|
|
|
public class RadiusMessage
|
|
{
|
|
public IPEndPoint EndPoint { get; set; }
|
|
|
|
public RadiusCode Code { get; set; }
|
|
|
|
byte identifier;
|
|
public byte Identifier
|
|
{
|
|
get => identifier;
|
|
set
|
|
{
|
|
identifier = value;
|
|
Authenticator = Guid.NewGuid().ToByteArray();
|
|
}
|
|
}
|
|
|
|
public byte[] Authenticator { get; set; }
|
|
|
|
List<RadiusAttribute> radiusAttributes = new List<RadiusAttribute>();
|
|
|
|
public RadiusMessage(IPEndPoint endPoint,RadiusCode radiusCode)
|
|
{
|
|
EndPoint = endPoint;
|
|
Code = radiusCode;
|
|
}
|
|
|
|
public byte[] Authenticate(byte[] secret)
|
|
{
|
|
byte[] packet = ToBytes();
|
|
|
|
MD5 md5 = MD5.Create();
|
|
md5.TransformBlock(packet, 0, packet.Length, null, 0);
|
|
md5.TransformFinalBlock(secret, 0, secret.Length);
|
|
Array.Copy(md5.Hash, 0, packet, 4, 16);
|
|
return packet;
|
|
}
|
|
|
|
public byte[] ToBytes()
|
|
{
|
|
using (MemoryStream memoryStream = new MemoryStream())
|
|
{
|
|
|
|
memoryStream.WriteByte((byte)Code);
|
|
memoryStream.WriteByte((byte)Identifier);
|
|
memoryStream.WriteShort((short)0);
|
|
memoryStream.WriteBytes(Authenticator);
|
|
|
|
foreach (RadiusAttribute radiusAttribute in radiusAttributes)
|
|
memoryStream.WriteBytes(radiusAttribute.ToBytes());
|
|
|
|
byte[] bytes = memoryStream.ToArray();
|
|
|
|
Array.Copy(
|
|
BitConverter.GetBytes((short)bytes.Length), 0,
|
|
bytes, 2,
|
|
2
|
|
);
|
|
|
|
return bytes;
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return String.Format("[RadiusMessage Code={0} Identifier={1} Attributes: {2}]",Code,Identifier,String.Join(", ",radiusAttributes));
|
|
}
|
|
|
|
public static RadiusMessage FromBytes(byte[] bytes,IPEndPoint remoteEndpoint)
|
|
{
|
|
if ((bytes.Length < 20) || (bytes.Length > 4096))
|
|
throw new ArgumentOutOfRangeException(nameof(bytes),"Radius packet needs to be sized between 20 and 4095 bytes");
|
|
|
|
RadiusMessage radiusMessage = new RadiusMessage(remoteEndpoint, (RadiusCode)bytes[0]);
|
|
using (Stream stream = new MemoryStream(bytes))
|
|
{
|
|
stream.ReadByte();
|
|
radiusMessage.Identifier = (byte)stream.ReadByte();
|
|
short plength = stream.ReadShort(true);
|
|
if (plength != bytes.Length)
|
|
throw new ArgumentException("packet: length != bytes.length");
|
|
|
|
radiusMessage.Authenticator = stream.ReadBytes(16);
|
|
|
|
while (stream.Position < stream.Length)
|
|
radiusMessage.radiusAttributes.Add(RadiusAttribute.Read(stream));
|
|
}
|
|
|
|
return radiusMessage;
|
|
}
|
|
}
|
|
}
|