BroadbandAntennaTrackingSystems
asked on
Mask Input via OpenSSH
Hello experts.
I have a Command Line application developed in .NET 2.0
I have the following code for masking specific user input that I do not want displayed in clear text.
protected string MaskPasswordInput()
{
IntPtr hStdIn = new IntPtr(CONIN);
int mode = 0;
char inputChar;
string password = "";
//Set console mode to read a character
//at a time and not echo input.
GetConsoleMode(hStdIn, ref mode);
mode = (mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));
SetConsoleMode(hStdIn, mode);
//Read the password a character at a time.
do
{
inputChar = (char)Console.Read();
if (inputChar >= 32)
{
//Echo character with password mask.
password += inputChar;
Console.Write("*");
}
} while (inputChar != '\r');//Enter pressed end of password.
//Set console back to line input
//mode if that's what you want.
mode = (mode | (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));
SetConsoleMode(hStdIn, mode);
return password;
}
This subroutine works fabulously via a telnet session. However when using Putty and OpenSSH the subroutine does not properly mask the input. Instead I see the clear text followed by the masked input characters. My best guess is this has to do with the echo or delay via SSH?
Any help or ideas would be greatly appreciated.
Cheers
I have a Command Line application developed in .NET 2.0
I have the following code for masking specific user input that I do not want displayed in clear text.
protected string MaskPasswordInput()
{
IntPtr hStdIn = new IntPtr(CONIN);
int mode = 0;
char inputChar;
string password = "";
//Set console mode to read a character
//at a time and not echo input.
GetConsoleMode(hStdIn, ref mode);
mode = (mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));
SetConsoleMode(hStdIn, mode);
//Read the password a character at a time.
do
{
inputChar = (char)Console.Read();
if (inputChar >= 32)
{
//Echo character with password mask.
password += inputChar;
Console.Write("*");
}
} while (inputChar != '\r');//Enter pressed end of password.
//Set console back to line input
//mode if that's what you want.
mode = (mode | (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));
SetConsoleMode(hStdIn, mode);
return password;
}
This subroutine works fabulously via a telnet session. However when using Putty and OpenSSH the subroutine does not properly mask the input. Instead I see the clear text followed by the masked input characters. My best guess is this has to do with the echo or delay via SSH?
Any help or ideas would be greatly appreciated.
Cheers
You might try the '-t' option for openssh, but with the little information I have I'm not sure, that this is your problem
-t Force pseudo-tty allocation. This can be used to execute arbi-
trary screen-based programs on a remote machine, which can be
very useful, e.g. when implementing menu services. Multiple -t
options force tty allocation, even if ssh has no local tty.
-t Force pseudo-tty allocation. This can be used to execute arbi-
trary screen-based programs on a remote machine, which can be
very useful, e.g. when implementing menu services. Multiple -t
options force tty allocation, even if ssh has no local tty.
ASKER
Gelonida,
Thanks for the feedback. I am using KTS KPYM Telnet Service on a Windows x86 environment. openSSH is being run under Cygwin on the same machine.
The ForceStart command of openSSH launches my .NET based Command Line Console.
I have openSSH registered as a start up service. So perhaps adding the -t command to the start up.
I have attempted to execute stty -echo prior to the password input and stty echo after the password input but this does not seem to quite work.
public void ToggleEcho(bool on)
{
try
{
int exitCode = -9999;
exitCode = CommandLineHelper.ExecuteC ommand(@"c :\cygwin\b in\stty.ex e",
(on ? "echo" : "-echo"), 120000);
Log.Info(("Exit Code " + exitCode));
}
catch (Exception ex)
{
Log.Error(ex);
}
}
I have also seen examples using the following command c:\cygwin\bin\sh.exe -c /bin/stty -echo
but still no success.
I'll let you know how the -t on the service start up works. Alternatively is there a variable I could set in the sshd_config file?
Thanks for the feedback. I am using KTS KPYM Telnet Service on a Windows x86 environment. openSSH is being run under Cygwin on the same machine.
The ForceStart command of openSSH launches my .NET based Command Line Console.
I have openSSH registered as a start up service. So perhaps adding the -t command to the start up.
I have attempted to execute stty -echo prior to the password input and stty echo after the password input but this does not seem to quite work.
public void ToggleEcho(bool on)
{
try
{
int exitCode = -9999;
exitCode = CommandLineHelper.ExecuteC
(on ? "echo" : "-echo"), 120000);
Log.Info(("Exit Code " + exitCode));
}
catch (Exception ex)
{
Log.Error(ex);
}
}
I have also seen examples using the following command c:\cygwin\bin\sh.exe -c /bin/stty -echo
but still no success.
I'll let you know how the -t on the service start up works. Alternatively is there a variable I could set in the sshd_config file?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks for the input. I'll give it a try.
ASKER
Gelonida,
Thanks for your suggestions. Sometimes it really helps to take a step back and get another perspective.
So I think the issue may reside in that the stty -echo command may only apply to the current cygwin instance.
Here was my base test case.
1) Open a cygwin shell test stty -echo and stty echo
Everything works great
2) open two cygwin shells
run stty -echo
see if these settings take effect on both shells.
Result. They do not.
So I would not expect that running stty -echo from another process as above would produce the desired result.
I am somewhat new to the cygwin environment so please forgive me if this is a newbie question. Is there a flag for stty -echo that I could use to control all open cygwin shells?
Thanks again for all your input
Thanks for your suggestions. Sometimes it really helps to take a step back and get another perspective.
So I think the issue may reside in that the stty -echo command may only apply to the current cygwin instance.
Here was my base test case.
1) Open a cygwin shell test stty -echo and stty echo
Everything works great
2) open two cygwin shells
run stty -echo
see if these settings take effect on both shells.
Result. They do not.
So I would not expect that running stty -echo from another process as above would produce the desired result.
I am somewhat new to the cygwin environment so please forgive me if this is a newbie question. Is there a flag for stty -echo that I could use to control all open cygwin shells?
Thanks again for all your input
Hi,
I'm not aware of a global flag. normally stty controls only the current terminal.
perhaps you clould again explain your exact use case:
I'm afraid I don't understand it.
Yoou have two Computers let's call them A and B
on A you installed an openssh server and a .NET command line application let's call it dotnet.exe
on B you have a cygwin=window
If you start dotnet.exe on A from a cmd window, then your password entry is hidden / masked, right?
if you start a cygwi wndow on B and ssh to A and try to strt dotnet.exe, then your password is not hidden/masked,
right?
What happens:
if you open a cygwin window on A and start dotnet.exe from there?
(without any stty -echo and so on ?? )
I'm not aware of a global flag. normally stty controls only the current terminal.
perhaps you clould again explain your exact use case:
I'm afraid I don't understand it.
Yoou have two Computers let's call them A and B
on A you installed an openssh server and a .NET command line application let's call it dotnet.exe
on B you have a cygwin=window
If you start dotnet.exe on A from a cmd window, then your password entry is hidden / masked, right?
if you start a cygwi wndow on B and ssh to A and try to strt dotnet.exe, then your password is not hidden/masked,
right?
What happens:
if you open a cygwin window on A and start dotnet.exe from there?
(without any stty -echo and so on ?? )
ASKER
Thank you again for your help.
Ok. So your synopsis is pretty much accurate.
When running cygwin shell on A and start dotnet.exe (TestConsole.exe) the echo is off. It currently does not turn back on but I think that has to do with looking for the eol character at the end of the password mask function.
I have seen an example were someone was writing out to /dev/tty each time. This may be worth evaluating if I can find the reference again. What are your thoughts? Is there anything there?
Ok. So your synopsis is pretty much accurate.
When running cygwin shell on A and start dotnet.exe (TestConsole.exe) the echo is off. It currently does not turn back on but I think that has to do with looking for the eol character at the end of the password mask function.
I have seen an example were someone was writing out to /dev/tty each time. This may be worth evaluating if I can find the reference again. What are your thoughts? Is there anything there?
ASKER
Link to /dev/tty example referenced above
http://groups.google.com/group/comp.lang.java.programmer/msg/a132c7feda18187a
http://groups.google.com/group/comp.lang.java.programmer/msg/a132c7feda18187a
Two more tests (I just try to narow down)
Test 1: ssh from A to A and run your program:
-------------------------- ---------- ---------- ---------- -
open a cygwin shell on A:
ssh localhost # use ssh and connect to yourself
#Now run
TestConsole.exe
# and just to have some more info
echo $TERM
Test 2: same as test 1, but ssh from B:
-------------------------- ---------- ---------- ------
open a cygwin shell on B:
ssh hostnameof_A # use ssh and connect to A
#Now run
TestConsole.exe
# and just to have some more info (it should be same as in Test1)
echo $TERM
Test 1: ssh from A to A and run your program:
--------------------------
open a cygwin shell on A:
ssh localhost # use ssh and connect to yourself
#Now run
TestConsole.exe
# and just to have some more info
echo $TERM
Test 2: same as test 1, but ssh from B:
--------------------------
open a cygwin shell on B:
ssh hostnameof_A # use ssh and connect to A
#Now run
TestConsole.exe
# and just to have some more info (it should be same as in Test1)
echo $TERM
ASKER
FYI, Here is the code example.
Will post results form above momentarily.
#CODE
class Program
{
static void Main(string[] args)
{
TTY_Test.Execute();
}
}
public class TTY_Test
{
public static void Execute()
{
int exitCode1;
int exitCode2;
Console.WriteLine("User: ");
string user = Console.ReadLine();
Console.WriteLine("Passwor d: ");
exitCode1 = ToggleEcho(false);
string password = Console.ReadLine();
exitCode2 = ToggleEcho(true);
Console.WriteLine("Toggle off Exit Code:" + exitCode1");
Console.WriteLine("Toggle on Exit Code:" + exitCode2");
Console.WriteLine("Done;") ;
Console.ReadLine();
}
protected static int ToggleEcho(bool on)
{
int exitCode = -9999;
try
{
//TODO: Add CommandLineHelper-e
exitCode = CommandLineHelper.ExecuteC ommand(@"c :\cygwin\b in\stty.ex e",
(on ? "echo" : "-echo"), 120000);
Console.WriteLine("Exit Code " + exitCode);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return exitCode;
}
}
#END CODE
Will post results form above momentarily.
#CODE
class Program
{
static void Main(string[] args)
{
TTY_Test.Execute();
}
}
public class TTY_Test
{
public static void Execute()
{
int exitCode1;
int exitCode2;
Console.WriteLine("User: ");
string user = Console.ReadLine();
Console.WriteLine("Passwor
exitCode1 = ToggleEcho(false);
string password = Console.ReadLine();
exitCode2 = ToggleEcho(true);
Console.WriteLine("Toggle off Exit Code:" + exitCode1");
Console.WriteLine("Toggle on Exit Code:" + exitCode2");
Console.WriteLine("Done;")
Console.ReadLine();
}
protected static int ToggleEcho(bool on)
{
int exitCode = -9999;
try
{
//TODO: Add CommandLineHelper-e
exitCode = CommandLineHelper.ExecuteC
(on ? "echo" : "-echo"), 120000);
Console.WriteLine("Exit Code " + exitCode);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return exitCode;
}
}
#END CODE
ASKER
Run Cygwin on A
echo $TERM
result cygwin
Run TestConsole.exe
User: user
Password: pass (echoes)
Toggle Off Exit Code: 0
Toggle On Exit Code: 0
echo $TERM
result cygwin
SSH from A to A
echo $TERM
result xterm
Run TestConsole.exe
User: user
Passwor: pass (echoes)
Toggle Off Exit Code: 0
Toggle On Exit Code: 0
echo $TERM
result xterm
echo $TERM
result cygwin
Run TestConsole.exe
User: user
Password: pass (echoes)
Toggle Off Exit Code: 0
Toggle On Exit Code: 0
echo $TERM
result cygwin
SSH from A to A
echo $TERM
result xterm
Run TestConsole.exe
User: user
Passwor: pass (echoes)
Toggle Off Exit Code: 0
Toggle On Exit Code: 0
echo $TERM
result xterm
ASKER
protected static int ToggleEcho(bool on)
{
int ExitCode = -9999;
try
{
//TODO: Add CommandLineHelper-e
ProcessStartInfo ProcessInfo;
System.Diagnostics.Process Process;
try
{
StringBuilder output = new StringBuilder();
ProcessInfo = new ProcessStartInfo(@"c:\cygw in\bin\stt y.exe", (on ? "echo" : "-echo"));
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecut e = false;
Process = System.Diagnostics.Process .Start(Pro cessInfo);
Process.WaitForExit(120000 );
ExitCode = Process.ExitCode;
Process.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error") ;
}
return ExitCode;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return ExitCode;
}
{
int ExitCode = -9999;
try
{
//TODO: Add CommandLineHelper-e
ProcessStartInfo ProcessInfo;
System.Diagnostics.Process
try
{
StringBuilder output = new StringBuilder();
ProcessInfo = new ProcessStartInfo(@"c:\cygw
ProcessInfo.CreateNoWindow
ProcessInfo.UseShellExecut
Process = System.Diagnostics.Process
Process.WaitForExit(120000
ExitCode = Process.ExitCode;
Process.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error")
}
return ExitCode;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return ExitCode;
}
ASKER
SSH from B to A
echo $TERM
result xterm
Run TestConsole.exe
User: user
Passwor: pass (echoes)
Toggle Off Exit Code: 0
Toggle On Exit Code: 0
echo $TERM
result xterm
echo $TERM
result xterm
Run TestConsole.exe
User: user
Passwor: pass (echoes)
Toggle Off Exit Code: 0
Toggle On Exit Code: 0
echo $TERM
result xterm
ASKER
when $TERM result is CYGWIN then setting the properties on the Console such as ECHO* and Console.ForegroundColor take effect, but not for XTERM
*ECHO in this case is achieved by
[System.Runtime.InteropSer vices.DllI mport("ker nel32")]
private static extern int SetConsoleMode(IntPtr hConsoleHandle,
int dwMode);
[System.Runtime.InteropSer vices.DllI mport("ker nel32")]
private static extern int GetConsoleMode(IntPtr hConsoleHandle,
ref int dwMode);
//Set console mode to read a character
//at a time and not echo input.
GetConsoleMode(hStdIn, ref mode);
mode = (mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));
SetConsoleMode(hStdIn, mode);
*ECHO in this case is achieved by
[System.Runtime.InteropSer
private static extern int SetConsoleMode(IntPtr hConsoleHandle,
int dwMode);
[System.Runtime.InteropSer
private static extern int GetConsoleMode(IntPtr hConsoleHandle,
ref int dwMode);
//Set console mode to read a character
//at a time and not echo input.
GetConsoleMode(hStdIn, ref mode);
mode = (mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));
SetConsoleMode(hStdIn, mode);
no idea, why the wrong terminal is detected and set.
but you can force the TERM variable in ~/.bashrc
by adding following line to it
export TERM=cygwin
but you can force the TERM variable in ~/.bashrc
by adding following line to it
export TERM=cygwin
ASKER
Thanks for the info. Do I need to set it /home/user/.bashrc or is there a way to default it for all users?
/etc/bash.bashrc should be for all users
If this doesn't work change /etc/profile
If this doesn't work change /etc/profile
ASKER
Thanks so much for all of your help... this has really be haunting me. I'll let you know how it goes!
Do you use putty / openssh interactively or is this an automated openssh call?
Could you specify your host on which you start telnet? (is it windows or cygwin telnet / is it started from a cmd window or from an xterm?)
Could you specify your host on which you started putty/ssh?