2

I am creating a TCP Server in Ruby and need to get a password from the user. This password should NOT echo. Unfortunately when I telnet to port 8080 and type: My password is echoed.

@server_socket = TCPServer.open(8080, localhost)
conn = @server_socket.accept
conn.write "Password: "
conn.gets.chomp # <-- This should not be visible

When I type telnet localhost 8080 I can see my password on the screen.

FlyingV
  • 2,207
  • 19
  • 18
  • password = conn.noecho(&:gets).chomp ## This doesn't work either – FlyingV Nov 01 '18 at 05:33
  • Do you mean that when you telnet and type out your password it appears in your console as you type it? Because that's a function of your client, not the server. – anothermh Nov 01 '18 at 06:22
  • @anothermh: Impossible? When a user telnets to a login screen; When he types in his password, it does not get displayed. THIS is a feature of the server not the client? ( – FlyingV Nov 01 '18 at 06:43
  • I thought you had to implement echoing on your own to begin with, does TCPServer really echo? Sounds like something that a regular TCPServer would not want. – Kimmo Lehto Nov 01 '18 at 07:11
  • It seems like thee should be a way to use `IO#getpass` method but when I try I get `Errno::ENXIO: Device not configured` – lacostenycoder Nov 01 '18 at 10:14

1 Answers1

3

You have to send the right byte sequence to the client to tell it to suppress local echo. These are described in RFC857.

I looked through a lot of resources on how to accomplish this and it's not very straightforward. This is what ended up working, though:

require 'socket'

server = TCPServer.open(2000)
client = server.accept

# Send the IAC DONT ECHO byte sequence
client.write "#{255.chr}#{254.chr}#{1.chr}"
# Send the IAC WILL ECHO byte sequence
client.write "#{255.chr}#{251.chr}#{1.chr}"

client.write 'Enter any text and it will not echo locally: '
text = client.gets.chomp
client.write "\r\n"
client.write "The text entered while echo was suppressed was #{text}\r\n"

# Send the IAC DO ECHO byte sequence
client.write "#{255.chr}#{253.chr}#{1.chr}"
# Send the IAC WONT ECHO byte sequence
client.write "#{255.chr}#{252.chr}#{1.chr}"

client.write 'Local echo has been re-enabled, enter any text: '
client.gets.chomp

client.close

The output in the telnet client is:

telnet localhost 2000
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Enter any text and it will not echo locally:
The text entered while echo was suppressed was foo
Local echo has been re-enabled, enter any text: bar
Connection closed by foreign host.

This solution is dependent upon the client telnet application supporting these modes and respecting them when they are requested. There is no guarantee that the client will honor them.

Community
  • 1
  • 1
anothermh
  • 9,815
  • 3
  • 33
  • 52
  • What telnet client are you using; I am using one for the mac? – FlyingV Nov 01 '18 at 17:49
  • I used brew to install telnet on macOS. `brew info telnet` shows `telnet: stable 60 (bottled)` using the formula `https://github.com/Homebrew/homebrew-core/blob/master/Formula/telnet.rb`. – anothermh Nov 01 '18 at 17:59
  • @FlyingV I'm curious to learn if this worked for you. It's an interesting problem. – anothermh Nov 02 '18 at 20:37