mirror of
https://github.com/jakobadam/RDSFactor.git
synced 2025-06-07 21:15:27 +02:00
Challange-Response: Follow the RFC spec
On Challange-Responses the result is sent back encrypted to the server. The shared RADIUS key is used for encryption. The State attribute necessary in challange request/responses is assigned a guid.
This commit is contained in:
parent
6ecba61ffd
commit
3d8463d7d8
10 changed files with 115 additions and 304 deletions
|
@ -15,17 +15,14 @@ Public Class RDSFactor
|
||||||
Public Shared ADField As String = ""
|
Public Shared ADField As String = ""
|
||||||
Public Shared ADMailField As String = ""
|
Public Shared ADMailField As String = ""
|
||||||
Public Shared EnableOTP As Boolean
|
Public Shared EnableOTP As Boolean
|
||||||
|
Public Shared secrets As NASAuthList
|
||||||
' Shared key: used for challange encryption
|
|
||||||
' TODO: Fix
|
|
||||||
Public Shared encCode As String = "gewsyy#sjs2!"
|
|
||||||
|
|
||||||
Private Shared DEBUG As Boolean
|
Private Shared DEBUG As Boolean
|
||||||
|
|
||||||
Private Shared UserAccessLog As New LogWriter
|
Private Shared UserAccessLog As New LogWriter
|
||||||
Private Shared Log As New LogWriter
|
Private Shared Log As New LogWriter
|
||||||
|
|
||||||
Private secrets As NASAuthList
|
|
||||||
Private radius1812 As RADIUSServer
|
Private radius1812 As RADIUSServer
|
||||||
Private radius1645 As RADIUSServer
|
Private radius1645 As RADIUSServer
|
||||||
Private userHash As New Hashtable
|
Private userHash As New Hashtable
|
||||||
|
@ -160,7 +157,7 @@ Public Class RDSFactor
|
||||||
If TSGW = "1" Then
|
If TSGW = "1" Then
|
||||||
handler = New RDSHandler(packet)
|
handler = New RDSHandler(packet)
|
||||||
Else
|
Else
|
||||||
handler = New CitrixHandler(packet)
|
'handler = New CitrixHandler(packet)
|
||||||
End If
|
End If
|
||||||
|
|
||||||
handler.ProcessRequest()
|
handler.ProcessRequest()
|
||||||
|
@ -254,7 +251,7 @@ Public Class RDSFactor
|
||||||
|
|
||||||
For i As Integer = 0 To ClientArray.Length - 1
|
For i As Integer = 0 To ClientArray.Length - 1
|
||||||
ServerLog("Loading Shared Secret for Client: " & ClientArray(i))
|
ServerLog("Loading Shared Secret for Client: " & ClientArray(i))
|
||||||
clientHash.Add(ClientArray(i), EncDec.Decrypt(RConfig.GetKeyValue("Clients", ClientArray(i)), encCode))
|
clientHash.Add(ClientArray(i), EncDec.Decrypt(RConfig.GetKeyValue("Clients", ClientArray(i)), "gewsyy#sjs2!"))
|
||||||
Next
|
Next
|
||||||
|
|
||||||
If ConfOk = True Then
|
If ConfOk = True Then
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<MyType>Console</MyType>
|
<MyType>Console</MyType>
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
<TargetFrameworkProfile>
|
||||||
|
</TargetFrameworkProfile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
@ -60,6 +61,7 @@
|
||||||
<Reference Include="System.DirectoryServices" />
|
<Reference Include="System.DirectoryServices" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.ServiceProcess" />
|
<Reference Include="System.ServiceProcess" />
|
||||||
|
<Reference Include="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
@ -80,7 +82,6 @@
|
||||||
<Compile Include="Crypto.vb" />
|
<Compile Include="Crypto.vb" />
|
||||||
<Compile Include="exceptions\MissingRadiusSecret.vb" />
|
<Compile Include="exceptions\MissingRadiusSecret.vb" />
|
||||||
<Compile Include="exceptions\MissingUser.vb" />
|
<Compile Include="exceptions\MissingUser.vb" />
|
||||||
<Compile Include="handlers\CitrixHandler.vb" />
|
|
||||||
<Compile Include="handlers\RDSHandler.vb" />
|
<Compile Include="handlers\RDSHandler.vb" />
|
||||||
<Compile Include="IniFileVb.vb" />
|
<Compile Include="IniFileVb.vb" />
|
||||||
<Compile Include="Log.vb" />
|
<Compile Include="Log.vb" />
|
||||||
|
@ -137,6 +138,7 @@
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Include="app.config" />
|
||||||
<None Include="My Project\app.manifest" />
|
<None Include="My Project\app.manifest" />
|
||||||
<None Include="My Project\Application.myapp">
|
<None Include="My Project\Application.myapp">
|
||||||
<Generator>MyApplicationCodeGenerator</Generator>
|
<Generator>MyApplicationCodeGenerator</Generator>
|
||||||
|
|
23
RDSFactor/app.config
Normal file
23
RDSFactor/app.config
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<system.diagnostics>
|
||||||
|
<sources>
|
||||||
|
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||||
|
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||||
|
<listeners>
|
||||||
|
<add name="FileLog"/>
|
||||||
|
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog"/>-->
|
||||||
|
</listeners>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
<switches>
|
||||||
|
<add name="DefaultSwitch" value="Information"/>
|
||||||
|
</switches>
|
||||||
|
<sharedListeners>
|
||||||
|
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||||
|
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||||
|
</sharedListeners>
|
||||||
|
</system.diagnostics>
|
||||||
|
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
|
|
@ -1,254 +0,0 @@
|
||||||
Imports System.DirectoryServices
|
|
||||||
Imports RADAR
|
|
||||||
|
|
||||||
' TODO: I don't use this! It's a leftover, moved out of the way
|
|
||||||
' from the CICRadarR.vb
|
|
||||||
'
|
|
||||||
' Look in RDSHandler how this should be refactored.
|
|
||||||
Public Class CitrixHandler
|
|
||||||
|
|
||||||
Private mPacket As RADIUSPacket
|
|
||||||
|
|
||||||
Public Sub New(packet As RADIUSPacket)
|
|
||||||
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
Private Sub ProcessPacketCSG(ByVal server As RADIUSServer, ByVal packet As RADIUSPacket)
|
|
||||||
|
|
||||||
' Let's take a look at just authentication requests,
|
|
||||||
' and drop other requests silently ...
|
|
||||||
|
|
||||||
If packet.Code <> RadiusPacketCode.AccessRequest Then
|
|
||||||
RDSFactor.AccessLog(mPacket, "Not a valid radius packet.. Drop!")
|
|
||||||
Exit Sub
|
|
||||||
End If
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
' Let's see if we have a username present ...
|
|
||||||
Dim username As RADIUSAttribute = packet.Attributes.GetFirstAttribute(RadiusAttributeType.UserName)
|
|
||||||
Dim pass As RADIUSAttribute = packet.Attributes.GetFirstAttribute(RadiusAttributeType.UserPassword)
|
|
||||||
Dim sid As String = ""
|
|
||||||
Dim mobile As String = ""
|
|
||||||
Dim smsCode As String = ""
|
|
||||||
Dim UserEmail As String = ""
|
|
||||||
|
|
||||||
|
|
||||||
' If an attribute of a particular type is not found, the function
|
|
||||||
' will return Nothing.
|
|
||||||
If username Is Nothing Then
|
|
||||||
' Technically, this case is against RFC, so ... drop.
|
|
||||||
RDSFactor.AccessLog(mPacket, "Not a valid radius packet.. No username pressent.. Drop!")
|
|
||||||
Exit Sub
|
|
||||||
End If
|
|
||||||
|
|
||||||
RDSFactor.AccessLog(mPacket, "Processing packet for user: " & username.ToString)
|
|
||||||
|
|
||||||
'If packetHash.ContainsKey(username.GetString & "_" & pass.GetString) Then
|
|
||||||
' Exit Sub
|
|
||||||
'End If
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Dim existState As Boolean = packet.Attributes.AttributeExists(RadiusAttributeType.State)
|
|
||||||
RDSFactor.AccessLog(mPacket, "Packet contains a state attribute? State=" & existState.ToString)
|
|
||||||
If existState = True Then ' Ok we have at packet with the State attribute set. Check if we can identify the authtentication packet.
|
|
||||||
Dim state As String = packet.Attributes.GetFirstAttribute(RadiusAttributeType.State).ToString
|
|
||||||
RDSFactor.AccessLog(mPacket, "Packet contains a state attribute State=" & state)
|
|
||||||
Dim UserDomain As String = ""
|
|
||||||
'lets see if user login using upd or UPN name
|
|
||||||
Dim sUserName As String = username.ToString
|
|
||||||
Dim sPassword As String = packet.UserPassword
|
|
||||||
|
|
||||||
RDSFactor.AccessLog(mPacket, "SMSToken supplied by user: " & sUserName)
|
|
||||||
|
|
||||||
sid = ""
|
|
||||||
If InStr(sUserName, "@") > 0 Then 'UPN
|
|
||||||
UserDomain = sUserName
|
|
||||||
Else 'UPD
|
|
||||||
'read domain from Hashtable
|
|
||||||
UserDomain = RDSFactor.NetBiosDomain & "\" & sUserName
|
|
||||||
End If
|
|
||||||
|
|
||||||
sid = EncDec.Encrypt(UserDomain & "_" & packet.UserPassword, RDSFactor.encCode)
|
|
||||||
RDSFactor.AccessLog(mPacket, "Checking for userHash " & sid)
|
|
||||||
If sid = state Then
|
|
||||||
packet.AcceptAccessRequest()
|
|
||||||
Else
|
|
||||||
packet.RejectAccessRequest()
|
|
||||||
End If
|
|
||||||
Else ' process the first login
|
|
||||||
|
|
||||||
' packetHash.Add(username.GetString & "_" & pass.GetString, 0)
|
|
||||||
|
|
||||||
' Console.WriteLine(username.GetString & " is trying to log in ... ")
|
|
||||||
' Note that an attribute can represent a string, number, IP, etc.
|
|
||||||
' RADAR will not guess that automatically, so use the appropriate
|
|
||||||
' function according to the attribute you're trying to read. Otherwise,
|
|
||||||
' the Value property is just a bunch of bytes as received in the
|
|
||||||
' RADIUS packet.
|
|
||||||
|
|
||||||
|
|
||||||
'Now lets get some information from ad if password is valid
|
|
||||||
Dim success As Boolean = False
|
|
||||||
Dim UserDomain As String = ""
|
|
||||||
'lets see if user login using upd or UPN name
|
|
||||||
Dim sUserName As String = username.ToString
|
|
||||||
Dim sPassword As String = packet.UserPassword
|
|
||||||
If InStr(sUserName, "@") > 0 Then 'UPN
|
|
||||||
UserDomain = sUserName
|
|
||||||
Else 'UPD
|
|
||||||
'read domain from Hashtable
|
|
||||||
UserDomain = RDSFactor.NetBiosDomain & "\" & sUserName
|
|
||||||
End If
|
|
||||||
|
|
||||||
RDSFactor.AccessLog(mPacket, "User " & UserDomain & " is trying to log in ...")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Try
|
|
||||||
Dim dirEntry As New DirectoryEntry("LDAP://" & RDSFactor.LDAPDomain, UserDomain, sPassword)
|
|
||||||
|
|
||||||
Dim obj As Object = dirEntry.NativeObject
|
|
||||||
Dim search As New DirectorySearcher(dirEntry)
|
|
||||||
|
|
||||||
If InStr(sUserName, "@") > 0 Then
|
|
||||||
search.Filter = "(userPrincipalName=" + sUserName + ")"
|
|
||||||
Else
|
|
||||||
search.Filter = "(SAMAccountName=" + sUserName + ")"
|
|
||||||
End If
|
|
||||||
'Load the Properties we need from AD
|
|
||||||
search.PropertiesToLoad.Add("distinguishedName")
|
|
||||||
'search.PropertiesToLoad.Add("primaryTelexNumber")
|
|
||||||
If RDSFactor.EnableOTP = True Then
|
|
||||||
If RDSFactor.EnableEmail = True Then
|
|
||||||
search.PropertiesToLoad.Add(RDSFactor.ADMailField)
|
|
||||||
End If
|
|
||||||
If RDSFactor.EnableSMS = True Then
|
|
||||||
search.PropertiesToLoad.Add(RDSFactor.ADField)
|
|
||||||
End If
|
|
||||||
|
|
||||||
End If
|
|
||||||
' Time to find out if user entered the correct username and pasword
|
|
||||||
RDSFactor.AccessLog(mPacket, "Trying to authenticate user agains Active Directory using te following parameters: " & "LDAPPAth: " & "LDAP://" & RDSFactor.LDAPDomain & ", Username: " & UserDomain & ", Password: " & sPassword)
|
|
||||||
|
|
||||||
Dim result As SearchResult = search.FindOne()
|
|
||||||
'Get the setting form AD. Yes we uses the field primaryTelexNumber, for who the f... still users telex. (I bet half the people reading this code don't even know what a telex is!)
|
|
||||||
'Dim code As String = DirectCast(result.Properties("primaryTelexNumber")(0), String)
|
|
||||||
'Dim aCode As String() = code.Split("/")
|
|
||||||
|
|
||||||
'Dim userLdap As String = "LDAP://" & LDAPPath & "/" & result.Properties("distinguishedName")(0)
|
|
||||||
'Dim userEntry As New DirectoryEntry(userLdap, UserDomain, sPassword)
|
|
||||||
If RDSFactor.EnableOTP = True Then
|
|
||||||
smsCode = RDSFactor.GenerateCode()
|
|
||||||
|
|
||||||
' REMEMBER to put at check for empty phone string
|
|
||||||
If RDSFactor.EnableEmail = True Then
|
|
||||||
Try
|
|
||||||
UserEmail = DirectCast(result.Properties(RDSFactor.ADMailField)(0), String)
|
|
||||||
|
|
||||||
If UserEmail.Trim.Length = 0 Or InStr(UserEmail, "@") = 0 Then
|
|
||||||
success = False
|
|
||||||
RDSFactor.AccessLog(mPacket, "Unable to find correct email for user " & UserDomain)
|
|
||||||
Else
|
|
||||||
success = True
|
|
||||||
End If
|
|
||||||
Catch
|
|
||||||
RDSFactor.AccessLog(mPacket, "Unable to find correct email for user " & UserDomain)
|
|
||||||
success = False
|
|
||||||
End Try
|
|
||||||
End If
|
|
||||||
If RDSFactor.EnableSMS = True Then
|
|
||||||
Try
|
|
||||||
mobile = DirectCast(result.Properties(RDSFactor.ADField)(0), String)
|
|
||||||
mobile = Replace(mobile, "+", "")
|
|
||||||
If mobile.Trim.Length = 0 Then
|
|
||||||
success = False
|
|
||||||
RDSFactor.AccessLog(mPacket, "Unable to find correct phone number for user " & UserDomain)
|
|
||||||
Else
|
|
||||||
success = True
|
|
||||||
End If
|
|
||||||
Catch
|
|
||||||
RDSFactor.AccessLog(mPacket, "Unable to find correct phone number for user " & UserDomain)
|
|
||||||
success = False
|
|
||||||
End Try
|
|
||||||
|
|
||||||
End If
|
|
||||||
|
|
||||||
sid = EncDec.Encrypt(UserDomain & "_" & smsCode, RDSFactor.encCode) 'generate unique code
|
|
||||||
End If
|
|
||||||
' sid = UserDomain & "_" & smsCode
|
|
||||||
'userEntry.Properties("primaryTelexNumber").Value = aCode(0) & "/" & smsCode & "/" & aCode(2) & "/" & aCode(3)
|
|
||||||
'userEntry.CommitChanges()
|
|
||||||
'userEntry.Dispose()
|
|
||||||
If 1 = 1 Then ' check if smscode is disabled for the user (Need to write this code)
|
|
||||||
'If userHash.ContainsKey(sid) Then
|
|
||||||
' userHash(sid) = sPassword
|
|
||||||
' If DEBUG = True Then
|
|
||||||
' CICRadarR.AccessLog(mPacket, "Updating userHash " & sid)
|
|
||||||
' End If
|
|
||||||
'Else
|
|
||||||
' userHash.Add(sid, sPassword)
|
|
||||||
' If DEBUG = True Then
|
|
||||||
' CICRadarR.AccessLog(mPacket, "Adding userHash " & sid)
|
|
||||||
' End If
|
|
||||||
'End If
|
|
||||||
' new code stored in AD now send it to the users phone
|
|
||||||
' Console.WriteLine(smsCode)
|
|
||||||
|
|
||||||
success = True
|
|
||||||
Else
|
|
||||||
success = False
|
|
||||||
End If
|
|
||||||
Catch
|
|
||||||
RDSFactor.AccessLog(mPacket, "Failed to authenticate user agains Active Directory using the following parameters: " & "LDAPPAth: " & "LDAP://" & RDSFactor.LDAPDomain & ", Username: " & UserDomain & ", Password: " & sPassword)
|
|
||||||
success = False
|
|
||||||
End Try
|
|
||||||
|
|
||||||
|
|
||||||
Dim attributes As New RADIUSAttributes
|
|
||||||
If success Then ' Yay! Someone guess the password ...
|
|
||||||
|
|
||||||
RDSFactor.AccessLog(mPacket, "User " & UserDomain & " authenticated agains Active Directory")
|
|
||||||
If RDSFactor.EnableOTP = True Then
|
|
||||||
Dim attr As New RADIUSAttribute(RadiusAttributeType.ReplyMessage, "SMS Token")
|
|
||||||
attributes.Add(attr)
|
|
||||||
Dim state As New RADIUSAttribute(RadiusAttributeType.State, sid)
|
|
||||||
attributes.Add(state)
|
|
||||||
' Console.WriteLine("len " & packet.Authenticator.Length.ToString)
|
|
||||||
server.SendAsResponse( _
|
|
||||||
New RADIUSPacket(RadiusPacketCode.AccessChallenge, _
|
|
||||||
packet.Identifier, attributes, _
|
|
||||||
packet.EndPoint), _
|
|
||||||
packet.Authenticator)
|
|
||||||
If RDSFactor.EnableSMS = True Then
|
|
||||||
RDSFactor.AccessLog(mPacket, "Sending access token: " & smsCode & " to phonenumber " & mobile)
|
|
||||||
Call RDSFactor.SendSMS(mobile, smsCode)
|
|
||||||
End If
|
|
||||||
If RDSFactor.EnableEmail = True Then
|
|
||||||
RDSFactor.AccessLog(mPacket, "Sending access token: " & smsCode & " to email " & UserEmail)
|
|
||||||
Call RDSFactor.SendEmail(UserEmail, smsCode)
|
|
||||||
End If
|
|
||||||
Else
|
|
||||||
RDSFactor.AccessLog(mPacket, "One time Password not enabled, so we let the user in")
|
|
||||||
packet.AcceptAccessRequest()
|
|
||||||
End If
|
|
||||||
' packetHash.Remove(username.GetString & "_" & pass.GetString)
|
|
||||||
Else ' Wrong username / password ...
|
|
||||||
|
|
||||||
RDSFactor.AccessLog(mPacket, "User " & UserDomain & " failed to authenticate against Active Directory")
|
|
||||||
Dim pk As New RADIUSPacket(RadiusPacketCode.AccessReject, packet.Identifier, Nothing, packet.EndPoint)
|
|
||||||
server.SendAsResponse(pk, packet.Authenticator)
|
|
||||||
' FYI ... if no additional attributes need to be added
|
|
||||||
' to the response, you can sepcify Nothing instead of
|
|
||||||
' creating an empty RADIUSAttributes object.
|
|
||||||
' packetHash.Remove(username.GetString & "_" & pass.GetString)
|
|
||||||
End If
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
|
|
||||||
End Class
|
|
|
@ -1,13 +1,20 @@
|
||||||
Imports System.DirectoryServices
|
Imports System.DirectoryServices
|
||||||
|
Imports System.Web.Helpers
|
||||||
Imports RADAR
|
Imports RADAR
|
||||||
|
|
||||||
Public Class RDSHandler
|
Public Class RDSHandler
|
||||||
|
|
||||||
|
' User -> Token that proves user has authenticated, but not yet proved
|
||||||
|
' herself with the 2. factor
|
||||||
|
Private Shared authTokens As New Hashtable
|
||||||
|
|
||||||
Private Shared userSessions As New Hashtable
|
Private Shared userSessions As New Hashtable
|
||||||
Private Shared sessionTimestamps As New Hashtable
|
Private Shared sessionTimestamps As New Hashtable
|
||||||
Private Shared userSidTokens As New Hashtable
|
Private Shared encryptedChallangeResults As New Hashtable
|
||||||
Private Shared userLaunchTimestamps As New Hashtable
|
Private Shared userLaunchTimestamps As New Hashtable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Private mPacket As RADIUSPacket
|
Private mPacket As RADIUSPacket
|
||||||
Private mUsername As String
|
Private mUsername As String
|
||||||
Private mPassword As String
|
Private mPassword As String
|
||||||
|
@ -210,27 +217,41 @@ Public Class RDSHandler
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private Sub ProcessChallengeResponse()
|
Private Sub ProcessChallengeResponse()
|
||||||
RDSFactor.AccessLog(mPacket, "ChallengeResponse")
|
Dim authToken = mPacket.Attributes.GetFirstAttribute(RadiusAttributeType.State).ToString
|
||||||
|
If Not authToken = authTokens(mUsername) Then
|
||||||
|
Throw New Exception("User is trying to respond to challange without valid auth token")
|
||||||
|
End If
|
||||||
|
|
||||||
' When the packet is an Challange-Response the password attr. contains the token
|
' When the packet is an Challange-Response the password attr. contains the encrypted result
|
||||||
Dim challangeCode = mPassword
|
Dim userEncryptedResult = mPassword
|
||||||
Dim state = mPacket.Attributes.GetFirstAttribute(RadiusAttributeType.State)
|
Dim localEncryptedResult = encryptedChallangeResults(mUsername)
|
||||||
|
|
||||||
Dim sid = EncDec.Encrypt(mUsername & "_" & challangeCode, RDSFactor.encCode)
|
If localEncryptedResult = userEncryptedResult Then
|
||||||
If sid = state.ToString Then
|
RDSFactor.AccessLog(mPacket, "ChallengeResponse Success")
|
||||||
userSidTokens.Remove(mUsername)
|
encryptedChallangeResults.Remove(mUsername)
|
||||||
|
authTokens.Remove(mUsername)
|
||||||
Accept()
|
Accept()
|
||||||
Else
|
Else
|
||||||
|
RDSFactor.AccessLog(mPacket, "Wrong challange code!")
|
||||||
mPacket.RejectAccessRequest()
|
mPacket.RejectAccessRequest()
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Private Sub TwoFactorChallenge()
|
Private Sub TwoFactorChallenge()
|
||||||
Dim code = RDSFactor.GenerateCode
|
Dim challangeCode = RDSFactor.GenerateCode
|
||||||
Dim sid = EncDec.Encrypt(mUsername & "_" & code, RDSFactor.encCode) 'generate unique code
|
Dim authToken = System.Guid.NewGuid.ToString
|
||||||
RDSFactor.AccessLog(mPacket, "Access Challange Code: " & code)
|
Dim clientIP = mPacket.EndPoint.Address.ToString
|
||||||
|
Dim sharedSecret = RDSFactor.secrets(clientIP)
|
||||||
|
|
||||||
userSidTokens(mUsername) = sid
|
RDSFactor.AccessLog(mPacket, "Access Challange Code: " & challangeCode)
|
||||||
|
|
||||||
|
If sharedSecret = Nothing Then
|
||||||
|
Throw New Exception("No shared secret for client:" & clientIP)
|
||||||
|
End If
|
||||||
|
|
||||||
|
authTokens(mUsername) = authToken
|
||||||
|
Dim encryptedChallangeResult = Crypto.SHA256(mUsername & challangeCode & sharedSecret)
|
||||||
|
encryptedChallangeResults(mUsername) = encryptedChallangeResult
|
||||||
|
|
||||||
If mUseSMSFactor Then
|
If mUseSMSFactor Then
|
||||||
RDSFactor.AccessLog(mPacket, "TODO: Send SMS")
|
RDSFactor.AccessLog(mPacket, "TODO: Send SMS")
|
||||||
|
@ -242,11 +263,11 @@ Public Class RDSHandler
|
||||||
|
|
||||||
Dim attributes As New RADIUSAttributes
|
Dim attributes As New RADIUSAttributes
|
||||||
|
|
||||||
Dim attr As New RADIUSAttribute(RadiusAttributeType.ReplyMessage, "SMS Token")
|
Dim replyMessageAttr As New RADIUSAttribute(RadiusAttributeType.ReplyMessage, "SMS Token")
|
||||||
Dim state As New RADIUSAttribute(RadiusAttributeType.State, sid)
|
Dim stateAttr As New RADIUSAttribute(RadiusAttributeType.State, authToken)
|
||||||
|
|
||||||
attributes.Add(attr)
|
attributes.Add(replyMessageAttr)
|
||||||
attributes.Add(state)
|
attributes.Add(stateAttr)
|
||||||
|
|
||||||
mPacket.SendAccessChallange(attributes)
|
mPacket.SendAccessChallange(attributes)
|
||||||
End Sub
|
End Sub
|
||||||
|
@ -310,7 +331,8 @@ Public Class RDSHandler
|
||||||
userSessions.Remove(username)
|
userSessions.Remove(username)
|
||||||
sessionTimestamps.Remove(username)
|
sessionTimestamps.Remove(username)
|
||||||
userLaunchTimestamps.Remove(username)
|
userLaunchTimestamps.Remove(username)
|
||||||
userSidTokens.Remove(username)
|
encryptedChallangeResults.Remove(username)
|
||||||
|
authTokens.Remove(username)
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End Sub
|
End Sub
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -38,9 +38,9 @@
|
||||||
<add key="ShowOptimizeExperience" value="true"/>
|
<add key="ShowOptimizeExperience" value="true"/>
|
||||||
<add key="OptimizeExperienceState" value="false"/>
|
<add key="OptimizeExperienceState" value="false"/>
|
||||||
<add key="SmsToken" value="true"/>
|
<add key="SmsToken" value="true"/>
|
||||||
<add key="RadiusServer" value="192.168.121.9"/>
|
<add key="RadiusServer" value="127.0.0.1"/>
|
||||||
<add key="RadiusSecret" value="helloworld"/>
|
<add key="RadiusSecret" value="helloworld"/>
|
||||||
<add key="OTP" value="true"/>
|
<add key="OTP" value="false"/>
|
||||||
<add key="EnableSMS" value="true"/>
|
<add key="EnableSMS" value="true"/>
|
||||||
<add key="EnableMail" value="false"/>
|
<add key="EnableMail" value="false"/>
|
||||||
</appSettings>
|
</appSettings>
|
||||||
|
@ -85,7 +85,11 @@
|
||||||
</authorization>
|
</authorization>
|
||||||
</personalization>
|
</personalization>
|
||||||
</webParts>
|
</webParts>
|
||||||
<compilation targetFramework="4.5"/>
|
<compilation targetFramework="4.5" debug="true">
|
||||||
|
<assemblies>
|
||||||
|
<add assembly="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
|
||||||
|
</assemblies>
|
||||||
|
</compilation>
|
||||||
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
|
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
|
||||||
</system.web>
|
</system.web>
|
||||||
<system.webServer>
|
<system.webServer>
|
||||||
|
@ -94,12 +98,10 @@
|
||||||
<add name="RDWAFormsAuthenticationModule" type="Microsoft.TerminalServices.Publishing.Portal.FormAuthentication.TSFormsAuthentication"/>
|
<add name="RDWAFormsAuthenticationModule" type="Microsoft.TerminalServices.Publishing.Portal.FormAuthentication.TSFormsAuthentication"/>
|
||||||
</modules>
|
</modules>
|
||||||
<security>
|
<security>
|
||||||
|
|
||||||
<authentication>
|
<authentication>
|
||||||
<windowsAuthentication enabled="false"/>
|
<windowsAuthentication enabled="false"/>
|
||||||
<anonymousAuthentication enabled="true"/>
|
<anonymousAuthentication enabled="true"/>
|
||||||
</authentication>
|
</authentication>
|
||||||
|
|
||||||
</security>
|
</security>
|
||||||
<httpRedirect enabled="false"/>
|
<httpRedirect enabled="false"/>
|
||||||
</system.webServer>
|
</system.webServer>
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
<?xml-stylesheet type="text/xsl" href="../Site.xsl"?>
|
<?xml-stylesheet type="text/xsl" href="../Site.xsl"?>
|
||||||
<?xml-stylesheet type="text/css" href="../RenderFail.css"?>
|
<?xml-stylesheet type="text/css" href="../RenderFail.css"?>
|
||||||
<% @Page Language="C#" Debug="false" ResponseEncoding="utf-8" ContentType="text/xml" %>
|
<% @Page Language="C#" Debug="false" ResponseEncoding="utf-8" ContentType="text/xml" %>
|
||||||
|
|
||||||
<% @Import Namespace="System" %>
|
<% @Import Namespace="System" %>
|
||||||
|
<% @Import Namespace="System.IO" %>
|
||||||
|
<% @Import Namespace="System.Web.Helpers" %>
|
||||||
<% @Import Namespace="System.Threading" %>
|
<% @Import Namespace="System.Threading" %>
|
||||||
<% @Import Namespace="System.Security" %>
|
<% @Import Namespace="System.Security" %>
|
||||||
<% @Import Namespace="Microsoft.TerminalServices.Publishing.Portal.FormAuthentication" %>
|
<% @Import Namespace="Microsoft.TerminalServices.Publishing.Portal.FormAuthentication" %>
|
||||||
|
@ -71,6 +74,7 @@
|
||||||
|
|
||||||
void Page_Load(object sender, EventArgs e)
|
void Page_Load(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
logit("pageload");
|
||||||
|
|
||||||
btnSignIn.Text = L_SubmitLabel_Text;
|
btnSignIn.Text = L_SubmitLabel_Text;
|
||||||
btnCancel.Text = L_CancelLabel_Text;
|
btnCancel.Text = L_CancelLabel_Text;
|
||||||
|
@ -87,18 +91,25 @@
|
||||||
RADIUSClient client = new RADIUSClient(RadiusServer, 1812, RadiusSecret);
|
RADIUSClient client = new RADIUSClient(RadiusServer, 1812, RadiusSecret);
|
||||||
RADIUSAttributes atts = new RADIUSAttributes();
|
RADIUSAttributes atts = new RADIUSAttributes();
|
||||||
client.Debug = Debug;
|
client.Debug = Debug;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
VendorSpecificAttribute vsa = new VendorSpecificAttribute(VendorSpecificType.Generic,(string)Session["Delivery"]);
|
VendorSpecificAttribute vsa = new VendorSpecificAttribute(VendorSpecificType.Generic,(string)Session["Delivery"]);
|
||||||
vsa.SetRADIUSAttribute(ref atts);
|
vsa.SetRADIUSAttribute(ref atts);
|
||||||
|
|
||||||
|
logit("AccessReqeust");
|
||||||
|
|
||||||
RADIUSPacket response = client.Authenticate(username, strPassword, atts);
|
RADIUSPacket response = client.Authenticate(username, strPassword, atts);
|
||||||
|
|
||||||
if (response.Code == RadiusPacketCode.AccessChallenge) {
|
if (response.Code == RadiusPacketCode.AccessChallenge) {
|
||||||
|
logit("Challange");
|
||||||
|
|
||||||
state = response.Attributes.GetFirstAttribute(RadiusAttributeType.State);
|
state = response.Attributes.GetFirstAttribute(RadiusAttributeType.State);
|
||||||
Session["State"] = state;
|
Session["State"] = state;
|
||||||
}
|
}
|
||||||
// Access-Accept
|
// Access-Accept
|
||||||
else if (response.Code == RadiusPacketCode.AccessAccept) {
|
else if (response.Code == RadiusPacketCode.AccessAccept) {
|
||||||
|
logit("Accept");
|
||||||
|
|
||||||
string sessionGuid = response.Attributes.GetFirstAttribute(RadiusAttributeType.ReplyMessage).GetString();
|
string sessionGuid = response.Attributes.GetFirstAttribute(RadiusAttributeType.ReplyMessage).GetString();
|
||||||
Session["SESSIONGUID"] = sessionGuid;
|
Session["SESSIONGUID"] = sessionGuid;
|
||||||
HttpCookie myCookie = new HttpCookie("RadiusSessionId");
|
HttpCookie myCookie = new HttpCookie("RadiusSessionId");
|
||||||
|
@ -173,17 +184,25 @@
|
||||||
Response.Redirect(strRedirectSafeUrl,false);
|
Response.Redirect(strRedirectSafeUrl,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void logit(String message) {
|
||||||
|
String path = "C:\\RDSFactor\\RDSFactorWeb\\RDWeb\\Pages\\log\\web.log";
|
||||||
|
message = DateTime.Now + ": " + message;
|
||||||
|
using (StreamWriter log = File.AppendText(path)) {
|
||||||
|
log.WriteLine(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void btnSignIn_Click(object sender, EventArgs e)
|
protected void btnSignIn_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
|
||||||
username = (string)Session["DomainUserName"];
|
username = (string)Session["DomainUserName"];
|
||||||
state = (RADIUSAttribute)Session["state"];
|
state = (RADIUSAttribute)Session["state"];
|
||||||
|
|
||||||
RADIUSClient myRadius = new RADIUSClient(RadiusServer, 1812, RadiusSecret);
|
RADIUSClient client = new RADIUSClient(RadiusServer, 1812, RadiusSecret);
|
||||||
RADIUSAttributes atts = new RADIUSAttributes();
|
RADIUSAttributes atts = new RADIUSAttributes();
|
||||||
|
|
||||||
atts.Add(state);
|
atts.Add(state);
|
||||||
RADIUSPacket response = myRadius.Authenticate(username, SmsToken.Text, atts);
|
String encryptedChallangeResult = Crypto.SHA256(username + SmsToken.Text + RadiusSecret);
|
||||||
|
RADIUSPacket response = client.Authenticate(username, encryptedChallangeResult, atts);
|
||||||
|
|
||||||
if (response.Code == RadiusPacketCode.AccessAccept)
|
if (response.Code == RadiusPacketCode.AccessAccept)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue