From 3d8463d7d84d2ee34018dc94e1425013dbaa7ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20Aar=C3=B8e=20Dam?= Date: Tue, 21 Apr 2015 12:52:04 +0200 Subject: [PATCH] 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. --- RDSFactor/My Project/Settings.Designer.vb | 30 +-- RDSFactor/RDSFactor.vb | 11 +- RDSFactor/RDSFactor.vbproj | 6 +- RDSFactor/app.config | 23 ++ RDSFactor/handlers/CitrixHandler.vb | 254 ------------------- RDSFactor/handlers/RDSHandler.vb | 56 ++-- RDSFactorWeb/RDWeb/Pages/Bin/RADAR.dll | Bin 46592 -> 46592 bytes RDSFactorWeb/RDWeb/Pages/Bin/RADAR.pdb | Bin 97792 -> 99840 bytes RDSFactorWeb/RDWeb/Pages/Web.config | 12 +- RDSFactorWeb/RDWeb/Pages/en-US/smstoken.aspx | 27 +- 10 files changed, 115 insertions(+), 304 deletions(-) create mode 100644 RDSFactor/app.config delete mode 100644 RDSFactor/handlers/CitrixHandler.vb diff --git a/RDSFactor/My Project/Settings.Designer.vb b/RDSFactor/My Project/Settings.Designer.vb index b24fb9d..7bf7d9d 100644 --- a/RDSFactor/My Project/Settings.Designer.vb +++ b/RDSFactor/My Project/Settings.Designer.vb @@ -13,15 +13,15 @@ Option Explicit On Namespace My - - _ + + _ Partial Friend NotInheritable Class MySettings Inherits Global.System.Configuration.ApplicationSettingsBase - - Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()), MySettings) - + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) + #Region "My.Settings Auto-Save Functionality" #If _MyType = "WindowsForms" Then Private Shared addedHandler As Boolean @@ -36,10 +36,10 @@ Namespace My End Sub #End If #End Region - + Public Shared ReadOnly Property [Default]() As MySettings Get - + #If _MyType = "WindowsForms" Then If Not addedHandler Then SyncLock addedHandlerLockObject @@ -57,13 +57,13 @@ Namespace My End Namespace Namespace My - - _ + + _ Friend Module MySettingsProperty - - _ + + _ Friend ReadOnly Property Settings() As Global.RDSFactor.My.MySettings Get Return Global.RDSFactor.My.MySettings.Default diff --git a/RDSFactor/RDSFactor.vb b/RDSFactor/RDSFactor.vb index edae5d1..c742d7b 100644 --- a/RDSFactor/RDSFactor.vb +++ b/RDSFactor/RDSFactor.vb @@ -15,17 +15,14 @@ Public Class RDSFactor Public Shared ADField As String = "" Public Shared ADMailField As String = "" Public Shared EnableOTP As Boolean - - ' Shared key: used for challange encryption - ' TODO: Fix - Public Shared encCode As String = "gewsyy#sjs2!" + Public Shared secrets As NASAuthList Private Shared DEBUG As Boolean Private Shared UserAccessLog As New LogWriter Private Shared Log As New LogWriter - Private secrets As NASAuthList + Private radius1812 As RADIUSServer Private radius1645 As RADIUSServer Private userHash As New Hashtable @@ -160,7 +157,7 @@ Public Class RDSFactor If TSGW = "1" Then handler = New RDSHandler(packet) Else - handler = New CitrixHandler(packet) + 'handler = New CitrixHandler(packet) End If handler.ProcessRequest() @@ -254,7 +251,7 @@ Public Class RDSFactor For i As Integer = 0 To ClientArray.Length - 1 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 If ConfOk = True Then diff --git a/RDSFactor/RDSFactor.vbproj b/RDSFactor/RDSFactor.vbproj index 1634894..6982b83 100644 --- a/RDSFactor/RDSFactor.vbproj +++ b/RDSFactor/RDSFactor.vbproj @@ -15,7 +15,8 @@ 512 Console v4.0 - Client + + x86 @@ -60,6 +61,7 @@ + @@ -80,7 +82,6 @@ - @@ -137,6 +138,7 @@ + MyApplicationCodeGenerator diff --git a/RDSFactor/app.config b/RDSFactor/app.config new file mode 100644 index 0000000..79551f5 --- /dev/null +++ b/RDSFactor/app.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RDSFactor/handlers/CitrixHandler.vb b/RDSFactor/handlers/CitrixHandler.vb deleted file mode 100644 index 9cbff01..0000000 --- a/RDSFactor/handlers/CitrixHandler.vb +++ /dev/null @@ -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 diff --git a/RDSFactor/handlers/RDSHandler.vb b/RDSFactor/handlers/RDSHandler.vb index c7529bb..0ec5d9a 100644 --- a/RDSFactor/handlers/RDSHandler.vb +++ b/RDSFactor/handlers/RDSHandler.vb @@ -1,13 +1,20 @@ Imports System.DirectoryServices +Imports System.Web.Helpers Imports RADAR 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 sessionTimestamps As New Hashtable - Private Shared userSidTokens As New Hashtable + Private Shared encryptedChallangeResults As New Hashtable Private Shared userLaunchTimestamps As New Hashtable + + Private mPacket As RADIUSPacket Private mUsername As String Private mPassword As String @@ -210,27 +217,41 @@ Public Class RDSHandler End Sub 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 - Dim challangeCode = mPassword - Dim state = mPacket.Attributes.GetFirstAttribute(RadiusAttributeType.State) + ' When the packet is an Challange-Response the password attr. contains the encrypted result + Dim userEncryptedResult = mPassword + Dim localEncryptedResult = encryptedChallangeResults(mUsername) - Dim sid = EncDec.Encrypt(mUsername & "_" & challangeCode, RDSFactor.encCode) - If sid = state.ToString Then - userSidTokens.Remove(mUsername) + If localEncryptedResult = userEncryptedResult Then + RDSFactor.AccessLog(mPacket, "ChallengeResponse Success") + encryptedChallangeResults.Remove(mUsername) + authTokens.Remove(mUsername) Accept() Else + RDSFactor.AccessLog(mPacket, "Wrong challange code!") mPacket.RejectAccessRequest() End If End Sub Private Sub TwoFactorChallenge() - Dim code = RDSFactor.GenerateCode - Dim sid = EncDec.Encrypt(mUsername & "_" & code, RDSFactor.encCode) 'generate unique code - RDSFactor.AccessLog(mPacket, "Access Challange Code: " & code) + Dim challangeCode = RDSFactor.GenerateCode + Dim authToken = System.Guid.NewGuid.ToString + 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 RDSFactor.AccessLog(mPacket, "TODO: Send SMS") @@ -242,11 +263,11 @@ Public Class RDSHandler Dim attributes As New RADIUSAttributes - Dim attr As New RADIUSAttribute(RadiusAttributeType.ReplyMessage, "SMS Token") - Dim state As New RADIUSAttribute(RadiusAttributeType.State, sid) + Dim replyMessageAttr As New RADIUSAttribute(RadiusAttributeType.ReplyMessage, "SMS Token") + Dim stateAttr As New RADIUSAttribute(RadiusAttributeType.State, authToken) - attributes.Add(attr) - attributes.Add(state) + attributes.Add(replyMessageAttr) + attributes.Add(stateAttr) mPacket.SendAccessChallange(attributes) End Sub @@ -310,7 +331,8 @@ Public Class RDSHandler userSessions.Remove(username) sessionTimestamps.Remove(username) userLaunchTimestamps.Remove(username) - userSidTokens.Remove(username) + encryptedChallangeResults.Remove(username) + authTokens.Remove(username) End If Next End Sub diff --git a/RDSFactorWeb/RDWeb/Pages/Bin/RADAR.dll b/RDSFactorWeb/RDWeb/Pages/Bin/RADAR.dll index 393a8431f79ff7328ae7a78b21652f2c7ccee756..1a3e0bbc2f115339e954062ae848f93fa5956a34 100644 GIT binary patch delta 13041 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 yr_Wlzt0W3DGu6z!L3ub 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 diff --git a/RDSFactorWeb/RDWeb/Pages/Web.config b/RDSFactorWeb/RDWeb/Pages/Web.config index 9582de2..1bb9a1a 100644 --- a/RDSFactorWeb/RDWeb/Pages/Web.config +++ b/RDSFactorWeb/RDWeb/Pages/Web.config @@ -38,9 +38,9 @@ - + - + @@ -85,7 +85,11 @@ - + + + + + @@ -94,12 +98,10 @@ - - diff --git a/RDSFactorWeb/RDWeb/Pages/en-US/smstoken.aspx b/RDSFactorWeb/RDWeb/Pages/en-US/smstoken.aspx index 3e46fb5..3f9da4f 100644 --- a/RDSFactorWeb/RDWeb/Pages/en-US/smstoken.aspx +++ b/RDSFactorWeb/RDWeb/Pages/en-US/smstoken.aspx @@ -2,7 +2,10 @@ <% @Page Language="C#" Debug="false" ResponseEncoding="utf-8" ContentType="text/xml" %> + <% @Import Namespace="System" %> +<% @Import Namespace="System.IO" %> +<% @Import Namespace="System.Web.Helpers" %> <% @Import Namespace="System.Threading" %> <% @Import Namespace="System.Security" %> <% @Import Namespace="Microsoft.TerminalServices.Publishing.Portal.FormAuthentication" %> @@ -71,7 +74,8 @@ void Page_Load(object sender, EventArgs e) { - + logit("pageload"); + btnSignIn.Text = L_SubmitLabel_Text; btnCancel.Text = L_CancelLabel_Text; @@ -87,18 +91,25 @@ RADIUSClient client = new RADIUSClient(RadiusServer, 1812, RadiusSecret); RADIUSAttributes atts = new RADIUSAttributes(); client.Debug = Debug; + try { VendorSpecificAttribute vsa = new VendorSpecificAttribute(VendorSpecificType.Generic,(string)Session["Delivery"]); vsa.SetRADIUSAttribute(ref atts); + logit("AccessReqeust"); + RADIUSPacket response = client.Authenticate(username, strPassword, atts); if (response.Code == RadiusPacketCode.AccessChallenge) { + logit("Challange"); + state = response.Attributes.GetFirstAttribute(RadiusAttributeType.State); Session["State"] = state; } // Access-Accept else if (response.Code == RadiusPacketCode.AccessAccept) { + logit("Accept"); + string sessionGuid = response.Attributes.GetFirstAttribute(RadiusAttributeType.ReplyMessage).GetString(); Session["SESSIONGUID"] = sessionGuid; HttpCookie myCookie = new HttpCookie("RadiusSessionId"); @@ -172,18 +183,26 @@ 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) { - username = (string)Session["DomainUserName"]; state = (RADIUSAttribute)Session["state"]; - RADIUSClient myRadius = new RADIUSClient(RadiusServer, 1812, RadiusSecret); + RADIUSClient client = new RADIUSClient(RadiusServer, 1812, RadiusSecret); RADIUSAttributes atts = new RADIUSAttributes(); 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) {