RDSFactor/CICRadarR/RADIUSServer.vb
2015-04-10 11:59:18 +02:00

161 lines
5.9 KiB
VB.net

Imports System.Net
Imports CICRadarR.Conversion
Public Class RADIUSServer
Private mSocket As UDPServer
Private mSecrets As NASAuthList
Private mLastAuthenticator() As Byte = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Public Delegate Sub RADIUSHandler(ByVal packet As RADIUSPacket)
Private HandlePacket As RADIUSHandler
Public Sub New(ByVal portNumber As Integer, ByVal onRADIUSPacket As RADIUSHandler, ByRef secrets As NASAuthList)
mSocket = New UDPServer(portNumber, AddressOf SocketData)
HandlePacket = onRADIUSPacket
mSecrets = secrets
End Sub
Public Sub New(ByVal ipAddress As String, ByVal portNumber As Integer, ByVal onRADIUSPacket As RADIUSHandler, ByRef secrets As NASAuthList)
mSocket = New UDPServer(ipAddress, portNumber, AddressOf SocketData)
HandlePacket = onRADIUSPacket
mSecrets = secrets
End Sub
Friend ReadOnly Property NASList() As NASAuthList
Get
Return mSecrets
End Get
End Property
Public Sub SendAsRequest(ByVal packet As RADIUSPacket)
If packet Is Nothing Then Exit Sub
If Not packet.IsValid Then Exit Sub
Dim data() As Byte = packet.Bytes
Dim hasher As System.Security.Cryptography.MD5 = System.Security.Cryptography.MD5.Create
Dim hash() As Byte = {}
Dim secret As String = mSecrets.GetSharedSecret(packet.EndPoint.Address.ToString)
Array.Resize(hash, data.Length + secret.Length)
data.CopyTo(hash, 0)
ConvertToBytes(secret).CopyTo(hash, data.Length)
hash = hasher.ComputeHash(hash)
hash.CopyTo(data, 4)
hash.CopyTo(mLastAuthenticator, 0)
mSocket.Send(data, packet.EndPoint)
End Sub
Public Sub SendAsResponse(ByVal packet As RADIUSPacket, ByVal requestAuth() As Byte)
Try
If packet Is Nothing Then
Exit Sub
End If
If Not packet.IsValid Then
Exit Sub
End If
If requestAuth Is Nothing Then
Exit Sub
End If
If requestAuth.Length <> 16 Then
Exit Sub
End If
Dim data() As Byte = packet.Bytes
Dim hasher As System.Security.Cryptography.MD5 = System.Security.Cryptography.MD5.Create
Dim hash() As Byte = {}
Dim secret As String = mSecrets.GetSharedSecret(packet.EndPoint.Address.ToString)
If secret = Nothing Then
Throw New MissingRadiusSecret(packet.EndPoint.Address.ToString)
End If
Array.Resize(hash, data.Length + secret.Length)
data.CopyTo(hash, 0)
ConvertToBytes(secret).CopyTo(hash, data.Length)
Array.Copy(requestAuth, 0, hash, 4, 16)
hash = hasher.ComputeHash(hash)
hash.CopyTo(data, 4)
mSocket.Send(data, packet.EndPoint)
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
Private Sub SocketData(ByRef data() As Byte, ByRef ep As IPEndPoint)
'Verify validity ...
If data.Length < 20 Then
Exit Sub
End If
Dim len As Integer = data(2) * 256 + data(3)
If data.Length <> len Then
Exit Sub
End If
Dim code As RadiusPacketCode = data(0)
Dim auth As Boolean
If code = RadiusPacketCode.AccessRequest Or code = RadiusPacketCode.AccountingRequest Then
auth = AuthenticateRequest(data, mSecrets.GetSharedSecret(ep.Address.ToString))
Else
auth = AuthenticateResponse(data, mSecrets.GetSharedSecret(ep.Address.ToString))
End If
If Not auth Then
Exit Sub
End If
Dim packet As New RADIUSPacket(data, ep, Me)
HandlePacket(packet)
End Sub
Private Function AuthenticateRequest(ByRef dataBytes() As Byte, ByVal secret As String) As Boolean
If dataBytes Is Nothing Then Return False
If dataBytes(0) = RadiusPacketCode.AccessRequest Then Return True
If secret Is Nothing Then Return False
Dim res As Boolean = True
Dim i As Integer
Dim hasher As System.Security.Cryptography.MD5 = System.Security.Cryptography.MD5.Create
Dim expectedHash() As Byte = {}
Array.Resize(Of Byte)(expectedHash, dataBytes.Length + secret.Length)
dataBytes.CopyTo(expectedHash, 0)
ConvertToBytes(secret).CopyTo(expectedHash, dataBytes.Length)
For i = 4 To 19 : expectedHash(i) = 0 : Next ' Setting authenticator to zero...
expectedHash = hasher.ComputeHash(expectedHash)
' Compare ...
i = 4 : Do While res And i <= 19 : If dataBytes(i) <> expectedHash(i - 4) Then : res = False : End If : i += 1 : Loop
Return res
End Function
Private Function AuthenticateResponse(ByRef dataBytes() As Byte, ByVal secret As String) As Boolean
If secret Is Nothing Then Return False
If secret = "" Then Return False
Dim res As Boolean = True
Dim i As Integer
Dim hasher As System.Security.Cryptography.MD5 = System.Security.Cryptography.MD5.Create
Dim expectedHash() As Byte = {}
Array.Resize(Of Byte)(expectedHash, dataBytes.Length + secret.Length)
dataBytes.CopyTo(expectedHash, 0)
ConvertToBytes(secret).CopyTo(expectedHash, dataBytes.Length)
For i = 4 To 19 : expectedHash(i) = mLastAuthenticator(i - 4) : Next ' Setting authenticator to zero...
expectedHash = hasher.ComputeHash(expectedHash)
' Compare ...
i = 4 : Do While res And i <= 19 : If dataBytes(i) <> expectedHash(i - 4) Then : res = False : End If : i += 1 : Loop
Return res
End Function
End Class