Skip to content

Instantly share code, notes, and snippets.

@codeodor
Last active January 6, 2016 12:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codeodor/6268372 to your computer and use it in GitHub Desktop.
Save codeodor/6268372 to your computer and use it in GitHub Desktop.
I need help with an error between Net::FTP and OpenSSL in Ruby.

I'm trying to get FTPFXP to work on Ruby 2.0 (so I can FTP over TLS)

I'm having problems with this line, which sets up the SSL Socket. OpenSSL checks whether @sock is a T_FILE

In Ruby 1.9.3, it worked well, because it was just a TCPSocket but in Ruby 2.0, @sock becomes a Net::FTP::BufferedSocket.

It's easy enough to change the code in https://github.com/codeodor/ftpfxp/blob/06f2d56e65e73d3818b6c7aef4dfe461bad98849/lib/ftpfxp/ftpfxptls.rb#L87 to send @sock.io to make it a TCPSocket again, but when Net::FTP tries to close the socket, it expects the socket to have a read timeout, which I'm guessing BufferedSocket has, but a TCPSocket does not.

So, a few questions:

  1. Should a Net::FTP::BufferedSocket be a File?
  2. Should Net::FTP be assuming it has a BufferedSocket at all times?
  3. Should TCPSocket implement read_timeout?

I guess the broader question is: what is the appropriate fix? Obviously I'll need to work around it in my code, but is this something that should be fixed in Ruby, and if so, where?

Thanks for your help!

@codeodor
Copy link
Author

The shutdown method is also not supported on a SSLSocket.

@codeodor
Copy link
Author

If we just monkeypatch null implementations of those 2 methods onto OpenSSL::SSL::SSLSocket it runs, but it only gets the first block, the 2nd call to read on the connection returns nil: https://github.com/ruby/ruby/blob/v2_0_0_247/lib/net/ftp.rb#L490

Updated: Ok, I was wrong about it only reading the first block. It's just the file I was testing on was much smaller than I expected. So the monkeypatching seems to work.

Now how do we fix this in Ruby, or is there anything wrong with Ruby?

@codeodor
Copy link
Author

I have also tried setting FTPFXP's @sock = BufferedSocket.new(socket_from_open_ssl) with no success.

@codeodor
Copy link
Author

I guess my first goal now is to get it to retrieve more than the 1st block, even if I have to monkeypatch stuff. Obviously prefer not to, but I need to make it work more than I need to make it pretty.

However, if problem is indeed from Ruby stdlib, then I'd love to figure it out and submit a pull request to fix it.

@codeodor
Copy link
Author

So, I thought I'd be clever and set SSLSocket's @io after it was initialized (to skip the type check in the C code):

@sock.instance_variable_set(:@io, original_sock)

But it was a segfault. 😄 (not when I set it, but when something attempted to use it)

@asheepen
Copy link

asheepen commented Jan 6, 2016

Hi,

we're facing the sameissue, but we're new to ruby. Can you explain your workaround a bit more in detail? Best would be some snippets of code.

Thanks

@asheepen
Copy link

asheepen commented Jan 6, 2016

meanwhile I get it working.

in ../openssl/ssl.rb

class SSLSocket

include Buffering

include SocketForwarder

include Nonblock

def shutdown(value)

end

def read_timeout=(sec)

end

und in ftpfxp-0-0.4/ftpfxp/ftpfxptls.rb

#82 : @sock = OpenSSL::SSL::SSLSocket.new(@sock.io, ctx)
#281 : conn = OpenSSL::SSL::SSLSocket.new(open_socket(host, port).io, ctx)

Is there another ( better ) solution. What did you do?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment