From 070abbc2ac5e9108963f89394d91f612c7647c0f Mon Sep 17 00:00:00 2001 From: "Jakob A. Dam" Date: Thu, 16 Apr 2015 14:27:30 +0200 Subject: [PATCH] Cleanup stale user sessions --- RDSFactor/RDSFactor.Designer.vb | 17 +++--- RDSFactor/RDSFactor.resx | 2 +- RDSFactor/RDSFactor.vb | 40 +++----------- RDSFactor/handlers/RDSHandler.vb | 91 ++++++++++++++++++++++---------- 4 files changed, 78 insertions(+), 72 deletions(-) diff --git a/RDSFactor/RDSFactor.Designer.vb b/RDSFactor/RDSFactor.Designer.vb index d64313d..a56e8b3 100644 --- a/RDSFactor/RDSFactor.Designer.vb +++ b/RDSFactor/RDSFactor.Designer.vb @@ -49,20 +49,21 @@ Partial Class RDSFactor ' Do not modify it using the code editor. _ Private Sub InitializeComponent() - Me.TimerCleanUpHash = New System.Timers.Timer() - CType(Me.TimerCleanUpHash, System.ComponentModel.ISupportInitialize).BeginInit() + Me.cleanupEvent = New System.Timers.Timer() + CType(Me.cleanupEvent, System.ComponentModel.ISupportInitialize).BeginInit() ' - 'TimerCleanUpHash + 'cleanupEvent ' - Me.TimerCleanUpHash.Enabled = True - Me.TimerCleanUpHash.Interval = 60000.0R + Me.cleanupEvent.Enabled = True + Me.cleanupEvent.Interval = 60000.0R ' - 'CICRadarR + 'RDSFactor ' Me.ServiceName = "Service1" - CType(Me.TimerCleanUpHash, System.ComponentModel.ISupportInitialize).EndInit() + CType(Me.cleanupEvent, System.ComponentModel.ISupportInitialize).EndInit() End Sub - Friend WithEvents TimerCleanUpHash As System.Timers.Timer + + Public WithEvents cleanupEvent As System.Timers.Timer End Class diff --git a/RDSFactor/RDSFactor.resx b/RDSFactor/RDSFactor.resx index 734d56d..e22b5c6 100644 --- a/RDSFactor/RDSFactor.resx +++ b/RDSFactor/RDSFactor.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + 17, 17 diff --git a/RDSFactor/RDSFactor.vb b/RDSFactor/RDSFactor.vb index 88ab61b..edae5d1 100644 --- a/RDSFactor/RDSFactor.vb +++ b/RDSFactor/RDSFactor.vb @@ -44,11 +44,6 @@ Public Class RDSFactor Private Shared SenderEmail As String = "" Private TSGW As String = "" - Private TSGWSessionIdHash As New Hashtable - Private TSGWSessionIdTimeStampHash As New Hashtable - Private TSGWLaunchIdTimeStampHash As New Hashtable - Private TSGWFirstLoginHash As New Hashtable ' Ensure that only one sms is send even if radius need to re-authenticate. - Private TSGWFirstLoginTimeStampHash As New Hashtable ' Ensure that only one sms is send even if radius need to re-authenticate. Public Shared SessionTimeOut As Integer = 30 ' in minutes Public Shared LaunchTimeOut As Integer = 30 ' in seconds @@ -131,11 +126,12 @@ Public Class RDSFactor Public Shared Sub AccessLog(packet As RADIUSPacket, message As String) Dim from_address = packet.EndPoint.Address.ToString - Dim log_message = Now & ": DEBUG: [" & packet.UserName & " " & from_address & "] " & message - AccessLog(log_message) + message = "[" & packet.UserName & " " & from_address & "] " & message + AccessLog(message) End Sub Public Shared Sub AccessLog(message As String) + message = Now & ": DEBUG: " & message If DEBUG = True Then UserAccessLog.WriteLog(message) @@ -350,34 +346,10 @@ Public Class RDSFactor End If Return "FAILED" End Try - - - End Function - Private Sub TimerCleanUpHash_Elapsed(sender As System.Object, e As System.Timers.ElapsedEventArgs) Handles TimerCleanUpHash.Elapsed - ' Clean Session and Launch hash for TSGW - Try - Dim Item As DictionaryEntry - For Each Item In TSGWSessionIdTimeStampHash - Dim hTime As DateTime = DirectCast(Item.Value, DateTime) - Dim tValid = DateDiff(DateInterval.Minute, hTime, Now) - If tValid >= SessionTimeOut Then - TSGWSessionIdTimeStampHash.Remove(Item.Key) - If TSGWSessionIdHash.Contains(Item.Key) Then - TSGWSessionIdHash.Remove(Item.Key) - End If - End If - Next - - For Each Item In TSGWLaunchIdTimeStampHash - Dim hTime As DateTime = DirectCast(Item.Value, DateTime) - Dim tValid = DateDiff(DateInterval.Second, hTime, Now) - If tValid >= LaunchTimeOut Then - TSGWLaunchIdTimeStampHash.Remove(Item.Key) - End If - Next - Catch - End Try + Public Sub CleanupEventHandler(sender, e) Handles cleanupEvent.Elapsed + RDSHandler.Cleanup() End Sub + End Class diff --git a/RDSFactor/handlers/RDSHandler.vb b/RDSFactor/handlers/RDSHandler.vb index a7e2cd0..c7529bb 100644 --- a/RDSFactor/handlers/RDSHandler.vb +++ b/RDSFactor/handlers/RDSHandler.vb @@ -5,10 +5,7 @@ Public Class RDSHandler Private Shared userSessions As New Hashtable Private Shared sessionTimestamps As New Hashtable - Private Shared userSidTokens As New Hashtable - Private Shared tokenTimestamps As New Hashtable - Private Shared userLaunchTimestamps As New Hashtable Private mPacket As RADIUSPacket @@ -80,36 +77,59 @@ Public Class RDSHandler ' When the packet is an AppLaunchRequest the password attribute contains the session id! Dim packetSessionId = mPassword Dim storedSessionId = userSessions(mUsername) - Dim sessionTimestamp = sessionTimestamps(mUsername) - If storedSessionId = Nothing Or sessionTimestamp = Nothing Then + If storedSessionId = Nothing Then RDSFactor.AccessLog(mPacket, "User has no session. MUST re-authenticate!") mPacket.RejectAccessRequest() Exit Sub End If - If packetSessionId = storedSessionId Then - Dim minsSinceLastActivity = DateDiff(DateInterval.Minute, sessionTimestamp, Now) - If minsSinceLastActivity < RDSFactor.SessionTimeOut Then - RDSFactor.AccessLog(mPacket, "Opening window") - ' Pro-long session - sessionTimestamps(storedSessionId) = Now - ' Open launch window - userLaunchTimestamps(mUsername) = Now - mPacket.AcceptAccessRequest() - Exit Sub - Else - RDSFactor.AccessLog(mPacket, "Session timed out -- User MUST re-authenticate") - userSessions.Remove(mUsername) - sessionTimestamps.Remove(mUsername) - End If - Else + If Not storedSessionId = packetSessionId Then RDSFactor.AccessLog(mPacket, "Stored session id didn't match packet session id!") + mPacket.RejectAccessRequest() + Exit Sub + End If + + If HasValidSession(mUsername) Then + RDSFactor.AccessLog(mPacket, "Opening window") + ' Pro-long user session + sessionTimestamps(mUsername) = Now + ' Open gateway connection window + userLaunchTimestamps(mUsername) = Now + mPacket.AcceptAccessRequest() + Exit Sub + Else + RDSFactor.AccessLog(mPacket, "Session timed out -- User MUST re-authenticate") + userSessions.Remove(mUsername) + sessionTimestamps.Remove(mUsername) + mPacket.RejectAccessRequest() End If - mPacket.RejectAccessRequest() End Sub + Public Shared Function HasValidLaunchWindow(username) As Boolean + Dim timestamp = userLaunchTimestamps(username) + + Dim secondsSinceLaunch = DateDiff(DateInterval.Second, timestamp, Now) + If secondsSinceLaunch < RDSFactor.LaunchTimeOut Then + Return True + Else + Return False + End If + End Function + + Public Shared Function HasValidSession(username) As Boolean + Dim id = userSessions(username) + Dim timestamp = sessionTimestamps(username) + + Dim minsSinceLastActivity = DateDiff(DateInterval.Minute, timestamp, Now) + If minsSinceLastActivity < RDSFactor.SessionTimeOut Then + Return True + Else + Return False + End If + End Function + ' Process the request from the Network Policy Server in the RDS Gateway. ' These are sent when an RDP client tries to connect through the Gateway. ' @@ -140,16 +160,15 @@ Public Class RDSHandler attributes.Add(proxyState) End If - Dim secondsSinceLaunch = DateDiff(DateInterval.Second, launchTimestamp, Now) - If secondsSinceLaunch < RDSFactor.LaunchTimeOut Then - RDSFactor.AccessLog(mPacket, "Opening gateway connection window") + If HasValidLaunchWindow(mUsername) Then + RDSFactor.AccessLog(mPacket, "Opening gateway launch window") mPacket.AcceptAccessRequest(attributes) Else - RDSFactor.AccessLog(mPacket, "Gateway connection window has timed out!") + RDSFactor.AccessLog(mPacket, "Gateway launch window has timed out!") + mPacket.RejectAccessRequest() End If - RDSFactor.AccessLog(mPacket, "Removing gateway connection window") - ' close window + RDSFactor.AccessLog(mPacket, "Removing gateway launch window") userLaunchTimestamps.Remove(mUsername) End Sub @@ -199,6 +218,7 @@ Public Class RDSHandler Dim sid = EncDec.Encrypt(mUsername & "_" & challangeCode, RDSFactor.encCode) If sid = state.ToString Then + userSidTokens.Remove(mUsername) Accept() Else mPacket.RejectAccessRequest() @@ -211,7 +231,6 @@ Public Class RDSHandler RDSFactor.AccessLog(mPacket, "Access Challange Code: " & code) userSidTokens(mUsername) = sid - tokenTimestamps(mUsername) = Now If mUseSMSFactor Then RDSFactor.AccessLog(mPacket, "TODO: Send SMS") @@ -282,5 +301,19 @@ Public Class RDSHandler Return email End Function + Public Shared Sub Cleanup() + RDSFactor.AccessLog("TimerCleanUp") + + Dim users = New ArrayList(userSessions.Keys) + For Each username In users + If Not HasValidSession(username) Then + userSessions.Remove(username) + sessionTimestamps.Remove(username) + userLaunchTimestamps.Remove(username) + userSidTokens.Remove(username) + End If + Next + End Sub + End Class