ronin-rb / ronin-support

A support library for Ronin. Like activesupport, but for hacking!
https://ronin-rb.dev
GNU Lesser General Public License v3.0
27 stars 9 forks source link

Should tcp_* with a block close the sockfd automatically ? #61

Closed danghvu closed 2 years ago

danghvu commented 11 years ago

I think it comes normally for a block to close its operation automatically. For example

>> a = open('/etc/passwd'){|f| p f}
#<File:/etc/passwd>
=> #<File:/etc/passwd (closed)>
>> a.read()
IOError: closed stream [(ronin):13:in `read'

But tcp_* does not close the connection thus it will remain until the end leaving the sockfd not to be reused.

>> s = tcp_connect('localhost',8080){|s| p s}
#<TCPSocket:fd 10>
=> #<TCPSocket:fd 10>
>> s = tcp_connect('localhost',8080){|s| p s}
#<TCPSocket:fd 11>
=> #<TCPSocket:fd 11>

btw, I also think tcp_send should return the data if the server return something instead of just return true

postmodern commented 11 years ago

Perhaps we should add a tcp_send_and_recv?

postmodern commented 11 years ago

Also you probably might want tcp_session. This will open the connect, yield the TCPSocket, and then close the connection.

tcp_session('localhost', 1337) do |socket|
  socket.send "data", 0
  puts socket.recv(1024)
end
danghvu commented 11 years ago

:+1: tcp_send_and_recv is actually quite useful. Any reason not to close a sock if a block is given ? If someone write it as block, he probably wants to close the socket at the end anyway.

postmodern commented 11 years ago

My original idea for allowing tcp_connect to accept a block was to allow setting up the connection, before returning it.

tcp_connect(host,port) do |socket|
  socket.puts "USER #{user}"
  socket.puts "PASS #{password}"
end

This is essentially the same thing as using Object#tap:

socket = tcp_connect(host,port).tap do |socket|
  ....
end

I probably should have originally combined tcp_connect and tcp_session into a single method that would close the connection if a block is given.

postmodern commented 11 years ago

How about a tcp_open method that either calls tcp_connect or tcp_session?

danghvu commented 11 years ago

Will it eventually deprecate tcp_connect and tcp_session ? I would prefer all the tcp_* family to have this close-after-block feature. I am using tcp_connect_and_send() with a block mostly since it saves me a sock.send :smile: and the block makes my code clear. I think it would be perfect if it saves me a sock.close too :smirk_cat: since closing the block generally means "I no longer need this connection"

postmodern commented 11 years ago

Very likely I will deprecate tcp_connect/tcp_session. Having to remember one method instead of two sounds much simpler.

I should also consider yielding the socket from tcp_send.

postmodern commented 11 years ago

The other Ronin::Network modules also define _connect and _session methods. I might merge them together as well. Would need to pick a good method name, esmtp_open sounds weird. Maybe shorten it to just esmtp()?

danghvu commented 11 years ago

:+1: tcp_send with a block, does the exact thing that I like. How about TCP.open(), SMTP.open() ? inspired from File.open

postmodern commented 11 years ago

The methods must be instance methods, so they can be included into exploits or the console. I thought about taking your original suggestion and merging the *_session behaviour into *_connect.

danghvu commented 11 years ago

I vote merging connect and session, also removing connect_and_send since tcp_send is just the same as it.

postmodern commented 2 years ago

All *_session methods have been combined into the *_connect methods in the 1.0.0 branch. Now when *_connect is passed a block it will close the connection once the block returns.