[Twisted-Python] Problem Reading a Directory with Conch/SFTP

I'm re-writing a client that downloads some data from a 3rd party using SFTP. The old client was written using Paramiko but I'd like to rewrite it using Twisted and Conch. Right now I'm running into an issue trying to get a directory listing from the remote server: 2011-08-22 13:35:03-0500 [SSHChannel session (0) on SSHService ssh-connection on _WrappingProtocol,client] Unhandled Error Traceback (most recent call last): File "/usr/lib64/python2.7/site-packages/twisted/python/log.py", line 84, in callWithLogger return callWithContext({"system": lp}, func, *args, **kw) File "/usr/lib64/python2.7/site-packages/twisted/python/log.py", line 69, in callWithContext return context.call({ILogContext: newCtx}, func, *args, **kw) File "/usr/lib64/python2.7/site-packages/twisted/python/context.py", line 118, in callWithContext return self.currentContext().callWithContext(ctx, func, *args, **kw) File "/usr/lib64/python2.7/site-packages/twisted/python/context.py", line 81, in callWithContext return func(*args,**kw) --- <exception caught here> --- File "/usr/lib64/python2.7/site-packages/twisted/conch/ssh/filetransfer.py", line 53, in dataReceived f(data) File "/usr/lib64/python2.7/site-packages/twisted/conch/ssh/filetransfer.py", line 711, in packet_STATUS msg, data = getNS(data) File "/usr/lib64/python2.7/site-packages/twisted/conch/ssh/common.py", line 36, in getNS l, = struct.unpack('!L',s[c:c+4]) struct.error: unpack requires a string argument of length 4 The problem seems to be that the remote SFTP implementation isn't returning complete status response message - it doesn't include the error message and the language identifier. I made a quite ugly workaround: diff --git a/twisted/conch/ssh/filetransfer.py b/twisted/conch/ssh/filetransfer. index 81a86fd..ed55b27 100644 --- a/twisted/conch/ssh/filetransfer.py +++ b/twisted/conch/ssh/filetransfer.py @@ -708,8 +708,15 @@ class FileTransferClient(FileTransferBase): d, data = self._parseRequest(data) code, = struct.unpack('!L', data[:4]) data = data[4:] - msg, data = getNS(data) - lang = getNS(data) + if len(data) >= 4: + msg, data = getNS(data) + if len(data) >= 4: + lang = getNS(data) + else: + lang = '' + else: + msg = '' + lang = '' if code == FX_OK: d.callback((msg, lang)) elif code == FX_EOF: Looking through the Paramiko code[1] it looks like it pads SFTP messages that are shorter than expected with null bytes. From what I saw in the SFTP I-D[2], a status message that doesn't include the error message and language code could be construed as legal even though they are not specifically marked as optional. [1] https://github.com/robey/paramiko/blob/master/paramiko/message.py#L103 [2] http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-4 -- Jeff Ollie

On Mon, Aug 22, 2011 at 3:02 PM, Jeffrey Ollie <jeff@ocjtech.us> wrote:
Wow... while googling for some other twisted/sftp related information, I came across this: http://twistedmatrix.com/trac/ticket/3009 -- Jeff Ollie

On Mon, Aug 22, 2011 at 3:02 PM, Jeffrey Ollie <jeff@ocjtech.us> wrote:
Wow... while googling for some other twisted/sftp related information, I came across this: http://twistedmatrix.com/trac/ticket/3009 -- Jeff Ollie
participants (2)
-
Glyph Lefkowitz
-
Jeffrey Ollie