@@ -14,6 +14,8 @@ class Msf::Sessions::LDAP
1414 # @return [Rex::Proto::LDAP::Client] The LDAP client
1515 attr_accessor :client
1616
17+ attr_accessor :keep_alive_thread
18+
1719 attr_accessor :platform , :arch
1820 attr_reader :framework
1921
@@ -26,6 +28,11 @@ def initialize(rstream, opts = {})
2628 super ( rstream , opts )
2729 end
2830
31+ def cleanup
32+ stop_keep_alive_loop
33+ super
34+ end
35+
2936 def bootstrap ( datastore = { } , handler = nil )
3037 session = self
3138 session . init_ui ( user_input , user_output )
@@ -139,4 +146,32 @@ def _interact_stream
139146 raise EOFError if ( console . stopped? == true )
140147 end
141148
149+ def on_registered
150+ start_keep_alive_loop
151+ end
152+
153+ # Start a background thread for regularly sending a no-op command to keep the connection alive
154+ def start_keep_alive_loop
155+ self . keep_alive_thread = framework . threads . spawn ( 'LDAP-shell-keepalive' , false ) do
156+ keep_alive_timeout = 10 * 60 # 10 minutes
157+ loop do
158+ if client . last_interaction . nil?
159+ remaining_sleep = keep_alive_timeout
160+ else
161+ remaining_sleep = keep_alive_timeout - ( Time . now - client . last_interaction )
162+ end
163+ sleep ( remaining_sleep )
164+ if ( Time . now - client . last_interaction ) > keep_alive_timeout
165+ client . search_root_dse
166+ end
167+ # This should have moved last_interaction forwards
168+ fail if ( Time . now - client . last_interaction ) > keep_alive_timeout
169+ end
170+ end
171+ end
172+
173+ # Stop the background thread
174+ def stop_keep_alive_loop
175+ keep_alive_thread . kill
176+ end
142177end
0 commit comments