@@ -284,6 +284,20 @@ def keepalive
284
284
# Reception
285
285
#
286
286
##
287
+
288
+ #
289
+ # Simple class to track packets and if they are in-progress or complete.
290
+ #
291
+ class QueuedPacket
292
+ attr_reader :packet
293
+ attr_reader :in_progress
294
+
295
+ def initialize ( packet , in_progress )
296
+ @packet = packet
297
+ @in_progress = in_progress
298
+ end
299
+ end
300
+
287
301
#
288
302
# Monitors the PacketDispatcher's sock for data in its own
289
303
# thread context and parsers all inbound packets.
@@ -306,8 +320,8 @@ def monitor_socket
306
320
begin
307
321
rv = Rex ::ThreadSafe . select ( [ self . sock . fd ] , nil , nil , PING_TIME )
308
322
if rv
309
- packet = receive_packet
310
- @pqueue << packet if packet
323
+ packet , in_progress = receive_packet
324
+ @pqueue << QueuedPacket . new ( packet , in_progress )
311
325
elsif self . send_keepalives && @pqueue . empty?
312
326
keepalive
313
327
end
@@ -342,11 +356,11 @@ def monitor_socket
342
356
tmp_channel = [ ]
343
357
tmp_close = [ ]
344
358
backlog . each do |pkt |
345
- if ( pkt . response? )
359
+ if ( pkt . packet . response? )
346
360
tmp_command << pkt
347
361
next
348
362
end
349
- if ( pkt . method == "core_channel_close" )
363
+ if ( pkt . packet . method == "core_channel_close" )
350
364
tmp_close << pkt
351
365
next
352
366
end
@@ -365,21 +379,23 @@ def monitor_socket
365
379
backlog . each do |pkt |
366
380
367
381
begin
368
- if ! dispatch_inbound_packet ( pkt )
382
+ if ! dispatch_inbound_packet ( pkt . packet , pkt . in_progress )
369
383
# Keep Packets in the receive queue until a handler is registered
370
384
# for them. Packets will live in the receive queue for up to
371
385
# PACKET_TIMEOUT seconds, after which they will be dropped.
372
386
#
373
387
# A common reason why there would not immediately be a handler for
374
388
# a received Packet is in channels, where a connection may
375
389
# open and receive data before anything has asked to read.
376
- if ( ::Time . now . to_i - pkt . created_at . to_i < PACKET_TIMEOUT )
390
+ #
391
+ # Also, don't bother saving incomplete packets if we have no handler.
392
+ if ( !pkt . in_progress and ::Time . now . to_i - pkt . packet . created_at . to_i < PACKET_TIMEOUT )
377
393
incomplete << pkt
378
394
end
379
395
end
380
396
381
397
rescue ::Exception => e
382
- dlog ( "Dispatching exception with packet #{ pkt } : #{ e } #{ e . backtrace } " , 'meterpreter' , LEV_1 )
398
+ dlog ( "Dispatching exception with packet #{ pkt . packet } : #{ e } #{ e . backtrace } " , 'meterpreter' , LEV_1 )
383
399
end
384
400
end
385
401
@@ -459,12 +475,16 @@ def add_response_waiter(request, completion_routine = nil, completion_param = ni
459
475
# Notifies a whomever is waiting for a the supplied response,
460
476
# if anyone.
461
477
#
462
- def notify_response_waiter ( response )
478
+ # For not-yet-complete responses, we might not be able to determine
479
+ # the response ID, in that case just let all waiters know that some
480
+ # responses are trickling in.
481
+ #
482
+ def notify_response_waiter ( response , in_progress = false )
463
483
handled = false
464
484
self . waiters . each ( ) { |waiter |
465
- if ( waiter . waiting_for? ( response ) )
466
- waiter . notify ( response )
467
- remove_response_waiter ( waiter )
485
+ if ( in_progress || waiter . waiting_for? ( response ) )
486
+ waiter . notify ( response , in_progress )
487
+ remove_response_waiter ( waiter ) unless in_progress
468
488
handled = true
469
489
break
470
490
end
@@ -498,7 +518,7 @@ def initialize_inbound_handlers
498
518
# Otherwise, the packet is passed onto any registered dispatch
499
519
# handlers until one returns success.
500
520
#
501
- def dispatch_inbound_packet ( packet )
521
+ def dispatch_inbound_packet ( packet , in_progress = false )
502
522
handled = false
503
523
504
524
# Update our last reply time
@@ -507,7 +527,7 @@ def dispatch_inbound_packet(packet)
507
527
# If the packet is a response, try to notify any potential
508
528
# waiters
509
529
if packet . response?
510
- if ( notify_response_waiter ( packet ) )
530
+ if ( notify_response_waiter ( packet , in_progress ) )
511
531
return true
512
532
end
513
533
end
0 commit comments