erlang / otp

Erlang/OTP
http://erlang.org
Apache License 2.0
11.41k stars 2.95k forks source link

ERL-1069: Support disabling echo input in new shell #4337

Open OTP-Maintainer opened 5 years ago

OTP-Maintainer commented 5 years ago

Original reporter: starbelly Affected versions: OTP-19.0, OTP-20.0, OTP-21.0, OTP-22.0 Component: stdlib Migrated from: https://bugs.erlang.org/browse/ERL-1069


Currently disabling input echo is only supported in the new shell. This prevents getting sensitive information at runtime in an escript (or similar) problematic. Currently in rebar3_hex and mix/hex we are clearing the input ever 1ms and while this works it is obviously not an ideal solution/situation security wise and at the very least leads to bad UX.

We did have a solution in rebar3_hex that worked for most platforms but bugs arose with it. Namely, opening up a tty_sl port does the job but subsequent io:get_line/1 calls never return after receiving input (seemingly). It is not 100% clear if this work-around is in fact a bug, so I did not open a bug report for it in favor of this is one feature request. Can gladly do so if that is what should be done.

Please find below a way to reproduce this behavior:
{code:erlang}
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -noshell -boot
%%
main(_) ->
    erlang:display({echo_off_support, io:setopts([{echo, false}])}),

    %% So we do a hack with tty_sl, which works but with a side effect that
    %% results in no subsequent calls able to return from an io:get_line/1 call
    Msg = <<"Enter your foo : ">>,
    error_logger:tty(false),
    Port = open_port({spawn, "tty_sl -e"}, [binary, eof]),
    port_command(Port, <<0, Msg/binary>>),
    receive
      {Port, {data, PwLine}} ->
             [Pw | _] = binary:split(PwLine, <<"\n">>),
             port_command(Port, <<0, $\n>>),
             port_close(Port),
            error_logger:tty(true),
            Pw
    end,
  io:get_line(<<"Enter your bar : ">>),
  erlang:display("We'll never make it here :("),
  halt(1).
{code}
OTP-Maintainer commented 5 years ago

starbelly said:

P.S. I'd be happy to do a PR, but perhaps would need a big of guidance. 
OTP-Maintainer commented 4 years ago

josevalim said:

If my understanding is correct, there is nothing to be done with the old shell because it does not intercept characters as they are typed. The trick that we use in Hex is to hide the characters by using "\r", see here: [https://github.com/hexpm/hex/blob/ab402f98c1efe6855c93dfc5130c2b7a4b1ef753/lib/mix/tasks/hex.ex#L363-L392]

 

Another option is to make `io:get_password` public API and make it available on the old shell too.
OTP-Maintainer commented 4 years ago

starbelly said:

@[~josevalim], yes, that's what is done in rebar3_hex as well based off what's done in hex :) We thought it was only needed when on windows, but then we ran into this problem and switched to the trick you allude to for all platforms. This works, but what would benefit everyone is for get_password/0 and get_password/1 to work on all platforms and within escripts. I'm going to look into this again over the coming weeks.
OTP-Maintainer commented 4 years ago

rickard said:

A PR would be appreciated
huangjia666 commented 1 year ago

I encountered a problem during Windows installation. When using bat to execute 'Install. exe', I will be prompted with a screen input of 'Do you want a minimum startup install of Sasl [No]:'. How can I skip this input?

max-au commented 1 year ago

IIRC, command line parameter -minimal was giving [No]. Could you try adding that to bat file?

huangjia666 commented 1 year ago

IIRC, command line parameter -minimal was giving [No]. Could you try adding that to bat file?

Thank you for your reply, but I tried adding the -minimal parameter and prompted 'Unknown command switch -minimal'. Can you give an example?

max-au commented 1 year ago

It was my bad, I confused Linux vs Windows Install. On Windows, you need to supply -s command line argument, e.g. Install.exe -s "....<path>...". Also, I think this specific GitHub issue is not related to your problem.

starbelly commented 5 months ago

This is old one! It seems io:get_password/0 and io:get_password/1 work solid in OTP 27. Should it be documented at this point in time?

garazdawi commented 5 months ago

I don't think it works properly on Windows yet. Maybe with the "lazy read" fix I proposed in #8113 we could get this working everything and then document it.

starbelly commented 5 months ago

@garazdawi It also doesn't work with noshell still. Yesterday I was messing around and created a false positive for myself, so to speak. I'm not sure it can be made to work with that, I'm not sure it can't either. Obviously, you would know best 😄 Since it doesn't work with noshell (such as with escripts), it might lead to lots of surprise (although it could be documented).

I looked at group.erl, it has been a while, but would it be possible to leverage edlin such that it would work?

garazdawi commented 3 weeks ago

9006 is an attempt at official support to get a password from the user. It only works in -noshell mode iff there is a terminal attached to stdin and stdout. If you want this functionality, please take the time to review and test the PR if it does what you want.