Skip to content

Instantly share code, notes, and snippets.

@u1735067
Last active June 17, 2021 07:32
Show Gist options
  • Save u1735067/3fbfb77fa529d137a508eac2118e7818 to your computer and use it in GitHub Desktop.
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)
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()
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