jbardin / scp.py

scp module for paramiko

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Retrieve scp errors

Yannik opened this issue · comments

I'm trying to use this lib with paramiko to push a config file to a fortigate. The fortigate has some validation logic to check if the config is valid or not.

Using openssh scp, that looks like this:

$ scp -O config admin@fortigate:fgt-restore-config
admin@fortigate's password: 
config                                                                                        100%  293KB   1.4MB/s   00:00    
500-Invalid config file

...and with -vvv (shortened to the relevant parts):

Sending file modes: C0644 300109 config
config                                                                                          0%    0     0.0KB/s   --:-- ETA
scp: debug2: fd 6 setting O_NONBLOCK
scp: debug1: fd 6 clearing O_NONBLOCK
debug2: channel 0: rcvd adjust 98321
debug2: channel 0: rcvd adjust 131072
config                                                                                        100%  293KB   1.5MB/s   00:00    
debug2: channel 0: read<=0 rfd 4 len 0
debug2: channel 0: read failed
debug2: chan_shutdown_read: channel 0: (i0 o0 sock -1 wfd 4 efd 6 [write])
debug2: channel 0: input open -> drain
debug2: channel 0: ibuf empty
debug2: channel 0: send eof
debug2: channel 0: input drain -> closed
debug2: channel 0: rcvd ext data 24
500-Invalid config file

I need to read the 500-Invalid config file output to validate whether the config push was successful or not.

I tried playing around with reading from self.channel.makefile() and self.channel.makefile_stderr() and with self.channel.recv(), but had no success at all.

@remram44 Do you have any idea how I could achieve this?

scp is supposed to show those, see _recv_confirm(). Do you get a different error?

@remram44 I get no errors at all, unfortunately.

Printing the msg in _recv_confirm() like this:

    def _recv_confirm(self):
        # read scp response
        msg = b''
        try:
            msg = self.channel.recv(512)
            print(msg)

shows

b'\x00'
b'\x00'
b'\x00'

You mean that the transfer succeeds either way (scp returns 0) but it prints this message?

You can try scp.channel.recv_stderr()

openssh scp indeed has an 0 exit code. (even though the error message is printed)

Calling scp.channel.recv_stderr() where scp is a SCPClient results in an AttributeError: 'NoneType' object has no attribute 'recv_stderr', presumably because putting a file closes the channel.

Modifying putfo directly to call print(scp.channel.recv_stderr(512)) after the self._send_file(fl, remote_path, mode, size=size) line results in a timeout error.

@remram44 the same (TimeoutError) occurs when calling self.channel.recv(512) instead of scp.channel.recv_stderr(512).

I have tried to sleep for a few seconds before calling these to make sure the other side had time to send the message, but that did not result in any change either.

Ok I don't know how this message is sent then, sorry.