Last active
June 17, 2021 07:32
-
-
Save u1735067/3fbfb77fa529d137a508eac2118e7818 to your computer and use it in GitHub Desktop.
Patch Paramiko channel.py to add channel logging (to debug SCP for example)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import paramiko | |
def patch_paramiko(): | |
from paramiko.common import DEBUG | |
recv_ori = paramiko.channel.Channel.recv | |
send_ori = paramiko.channel.Channel.send | |
exec_command_ori = paramiko.channel.Channel.exec_command | |
def patched_exec_command(self, command): | |
self._log(DEBUG, 'Executing command: {}'.format(command)) | |
return exec_command_ori(self, command) | |
def patched_recv(self, nbytes): | |
out = recv_ori(self, nbytes) | |
self._log(DEBUG, 'recv: {}'.format(out)) | |
return out | |
def patched_send(self, s, from_all=False): | |
if not from_all: | |
self._log(DEBUG, 'send: {}'.format(s if isinstance(s, bytes) else s.encode('utf-8'))) | |
return send_ori(self, s) | |
def patched_sendall(self, s): | |
self._log(DEBUG, 'sendall: {}'.format(s if isinstance(s, bytes) else s.encode('utf-8'))) | |
while s: | |
sent = self.send(s, True) | |
s = s[sent:] | |
return None | |
paramiko.channel.Channel.exec_command = patched_exec_command | |
paramiko.channel.Channel.recv = patched_recv | |
paramiko.channel.Channel.send = patched_send | |
paramiko.channel.Channel.sendall = patched_sendall | |
import logging | |
logging.basicConfig(level=logging.DEBUG) | |
patch_paramiko() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/channel.py b/channel.patched.py | |
index 41b1895..2766b94 100644 | |
--- a/channel.py | |
+++ b/channel.patched.py | |
@@ -187,6 +187,9 @@ class Channel(ClosingContextManager): | |
`.SSHException` -- if the request was rejected or the channel was | |
closed | |
""" | |
+ self._log(DEBUG, 'Requesting PTY (termtype={}, width={}, heigth={}, width_pixel={}, heigth_pixel={})'.format( | |
+ term, width, height, width_pixels, height_pixels | |
+ )) | |
m = Message() | |
m.add_byte(cMSG_CHANNEL_REQUEST) | |
m.add_int(self.remote_chanid) | |
@@ -220,6 +223,7 @@ class Channel(ClosingContextManager): | |
`.SSHException` -- if the request was rejected or the channel was | |
closed | |
""" | |
+ self._log(DEBUG, 'Invoking shell') | |
m = Message() | |
m.add_byte(cMSG_CHANNEL_REQUEST) | |
m.add_int(self.remote_chanid) | |
@@ -246,6 +250,7 @@ class Channel(ClosingContextManager): | |
`.SSHException` -- if the request was rejected or the channel was | |
closed | |
""" | |
+ self._log(DEBUG, 'Executing command: {}'.format(command)) | |
m = Message() | |
m.add_byte(cMSG_CHANNEL_REQUEST) | |
m.add_int(self.remote_chanid) | |
@@ -272,6 +277,7 @@ class Channel(ClosingContextManager): | |
`.SSHException` -- if the request was rejected or the channel was | |
closed | |
""" | |
+ self._log(DEBUG, 'Invoking subsystem: {}'.format(subsystem)) | |
m = Message() | |
m.add_byte(cMSG_CHANNEL_REQUEST) | |
m.add_int(self.remote_chanid) | |
@@ -297,6 +303,9 @@ class Channel(ClosingContextManager): | |
`.SSHException` -- if the request was rejected or the channel was | |
closed | |
""" | |
+ self._log(DEBUG, 'Resizing PTY (width={}, heigth={}, width_pixel={}, heigth_pixel={})'.format( | |
+ width, height, width_pixels, height_pixels | |
+ )) | |
m = Message() | |
m.add_byte(cMSG_CHANNEL_REQUEST) | |
m.add_int(self.remote_chanid) | |
@@ -709,6 +718,7 @@ class Channel(ClosingContextManager): | |
m.add_int(ack) | |
self.transport._send_user_message(m) | |
+ self._log(DEBUG, 'recv: {}'.format(out)) | |
return out | |
def recv_stderr_ready(self): | |
@@ -757,6 +767,7 @@ class Channel(ClosingContextManager): | |
m.add_int(ack) | |
self.transport._send_user_message(m) | |
+ self._log(DEBUG, 'recv stderr: {}'.format(out)) | |
return out | |
def send_ready(self): | |
@@ -772,6 +783,7 @@ class Channel(ClosingContextManager): | |
``True`` if a `send` call on this channel would immediately succeed | |
or fail | |
""" | |
+ self._log(DEBUG, 'send ready') | |
self.lock.acquire() | |
try: | |
if self.closed or self.eof_sent: | |
@@ -795,6 +807,7 @@ class Channel(ClosingContextManager): | |
by `settimeout`. | |
""" | |
+ self._log(DEBUG, 'send: {}'.format(s if isinstance(s, bytes) else s.encode('utf-8'))) | |
m = Message() | |
m.add_byte(cMSG_CHANNEL_DATA) | |
m.add_int(self.remote_chanid) | |
@@ -818,6 +831,7 @@ class Channel(ClosingContextManager): | |
.. versionadded:: 1.1 | |
""" | |
+ self._log(DEBUG, 'send stderr: {}'.format(s if isinstance(s, bytes) else s.encode('utf-8'))) | |
m = Message() | |
m.add_byte(cMSG_CHANNEL_EXTENDED_DATA) | |
m.add_int(self.remote_chanid) | |
@@ -842,6 +856,7 @@ class Channel(ClosingContextManager): | |
sent, there is no way to determine how much data (if any) was sent. | |
This is irritating, but identically follows Python's API. | |
""" | |
+ self._log(DEBUG, 'sendall: {}'.format(s if isinstance(s, bytes) else s.encode('utf-8'))) | |
while s: | |
sent = self.send(s) | |
s = s[sent:] | |
@@ -863,6 +878,7 @@ class Channel(ClosingContextManager): | |
.. versionadded:: 1.1 | |
""" | |
+ self._log(DEBUG, 'sendall stderr: {}'.format(s if isinstance(s, bytes) else s.encode('utf-8'))) | |
while s: | |
sent = self.send_stderr(s) | |
s = s[sent:] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment