22
33class Net ::SSH ::CommandStream
44
5- attr_accessor :channel , :thread , :error , :ssh
5+ attr_accessor :channel , :thread , :error , :ssh , :session
66 attr_accessor :lsock , :rsock , :monitor
77
88 module PeerInfo
@@ -13,7 +13,9 @@ module PeerInfo
1313
1414 def shell_requested ( channel , success )
1515 unless success
16- raise Net ::SSH ::ChannelRequestFailed , 'Shell/exec channel request failed'
16+ error = Net ::SSH ::ChannelRequestFailed , 'Shell/exec channel request failed'
17+ handle_error ( error : error )
18+ raise error
1719 end
1820
1921 self . channel = channel
@@ -40,7 +42,8 @@ def shell_requested(channel, success)
4042 end
4143 end
4244
43- def initialize ( ssh , cmd = nil , pty : false , cleanup : false )
45+ def initialize ( ssh , cmd = nil , pty : false , cleanup : false , session : nil )
46+ self . session = session
4447 self . lsock , self . rsock = Rex ::Socket . tcp_socket_pair ( )
4548 self . lsock . extend ( Rex ::IO ::Stream )
4649 self . lsock . extend ( PeerInfo )
@@ -74,31 +77,42 @@ def initialize(ssh, cmd = nil, pty: false, cleanup: false)
7477 end
7578
7679 channel . on_open_failed do |ch , code , desc |
77- raise Net ::SSH ::ChannelOpenFailed . new ( code , 'Session channel open failed' )
80+ error = Net ::SSH ::ChannelOpenFailed . new ( code , 'Session channel open failed' )
81+ handle_error ( error : error )
82+ raise error
7883 end
7984
8085 self . monitor = Thread . new do
81- while ( true )
82- next if not self . rsock . has_read_data? ( 1.0 )
83- buff = self . rsock . read ( 16384 )
84- break if not buff
85- verify_channel
86- self . channel . send_data ( buff ) if buff
86+ begin
87+ Kernel . loop do
88+ next if not self . rsock . has_read_data? ( 1.0 )
89+
90+ buff = self . rsock . read ( 16384 )
91+ break if not buff
92+
93+ verify_channel
94+ self . channel . send_data ( buff ) if buff
95+ end
96+ rescue ::StandardError => e
97+ handle_error ( error : e )
8798 end
8899 end
89100
90- while true
91- rssh . process ( 0.5 ) { true }
101+ begin
102+ Kernel . loop { rssh . process ( 0.5 ) { true } }
103+ rescue ::StandardError => e
104+ handle_error ( error : e )
92105 end
93106
94107 # Shut down the SSH session if requested
95108 if !rcmd . nil? && rcleanup
96109 rssh . close
97110 end
98111 end
112+ self . thread . abort_on_exception = true
99113 rescue ::StandardError => e
100114 # XXX: This won't be set UNTIL there's a failure from a thread
101- self . error = e
115+ handle_error ( error : e )
102116 ensure
103117 self . monitor . kill if self . monitor
104118 end
@@ -119,6 +133,7 @@ def handle_error(error: nil)
119133 end
120134
121135 def cleanup
136+ self . session . alive = false if self . session
122137 self . monitor . kill
123138 self . lsock . close rescue nil
124139 self . rsock . close rescue nil
0 commit comments