pub fn get_input(
prompt: &str,
default_value: Option<&str>,
echo: bool,
verify: bool,
) -> Option<String>Expand description
A utility function that will prompt the user for input via the console/tty.
prompt is the text to show to the user.
default_value can be used to pre-set the answer, allowing the
user to simply press enter.
echo, if true, means to show the user’s answer on the screen
as they type it. If false, means to conceal it.
verify, if true, will ask the user for their input twice in
order to confirm that they provided the same text both times.
This is useful when creating a password and echo == false.
Examples found in repository?
examples/whoami.rs (line 38)
37fn prompt(prompt: &str, echo: bool) -> SshResult<String> {
38 get_input(prompt, None, echo, false).ok_or_else(|| Error::Fatal("reading password".to_string()))
39}
40
41fn prompt_stdin(prompt: &str) -> SshResult<String> {
42 eprintln!("{}", prompt);
43 let mut input = String::new();
44 let _ = std::io::stdin().read_line(&mut input)?;
45 Ok(input.trim().to_string())
46}
47
48fn authenticate(sess: &Session, user_name: Option<&str>) -> SshResult<()> {
49 match sess.userauth_none(user_name)? {
50 AuthStatus::Success => return Ok(()),
51 _ => {}
52 }
53
54 loop {
55 let auth_methods = sess.userauth_list(user_name)?;
56
57 if auth_methods.contains(AuthMethods::PUBLIC_KEY) {
58 match sess.userauth_public_key_auto(None, None)? {
59 AuthStatus::Success => return Ok(()),
60 _ => {}
61 }
62 }
63
64 if auth_methods.contains(AuthMethods::INTERACTIVE) {
65 loop {
66 match sess.userauth_keyboard_interactive(None, None)? {
67 AuthStatus::Success => return Ok(()),
68 AuthStatus::Info => {
69 let info = sess.userauth_keyboard_interactive_info()?;
70 if !info.instruction.is_empty() {
71 eprintln!("{}", info.instruction);
72 }
73 let mut answers = vec![];
74 for p in &info.prompts {
75 answers.push(prompt(&p.prompt, p.echo)?);
76 }
77 sess.userauth_keyboard_interactive_set_answers(&answers)?;
78
79 continue;
80 }
81 AuthStatus::Denied => {
82 break;
83 }
84 status => {
85 return Err(Error::Fatal(format!(
86 "interactive auth status: {:?}",
87 status
88 )))
89 }
90 }
91 }
92 }
93
94 if auth_methods.contains(AuthMethods::PASSWORD) {
95 let pw = prompt("Password: ", false)?;
96
97 match sess.userauth_password(user_name, Some(&pw))? {
98 AuthStatus::Success => return Ok(()),
99 status => return Err(Error::Fatal(format!("password auth status: {:?}", status))),
100 }
101 }
102
103 return Err(Error::Fatal("unhandled auth case".to_string()));
104 }
105}
106
107fn main() -> SshResult<()> {
108 let sess = Session::new()?;
109 sess.set_auth_callback(|prompt, echo, verify, identity| {
110 let prompt = match identity {
111 Some(ident) => format!("{} ({}): ", prompt, ident),
112 None => prompt.to_string(),
113 };
114 get_input(&prompt, None, echo, verify)
115 .ok_or_else(|| Error::Fatal("reading password".to_string()))
116 });
117
118 sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119 // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120 sess.options_parse_config(None)?;
121 sess.connect()?;
122 eprintln!(
123 "using {} as user name for authentication",
124 sess.get_user_name()?
125 );
126 verify_known_hosts(&sess)?;
127
128 authenticate(&sess, None)?;
129
130 let channel = sess.new_channel()?;
131 channel.open_session()?;
132 channel.request_exec("whoami")?;
133 channel.send_eof()?;
134
135 let mut stdout = String::new();
136 channel.stdout().read_to_string(&mut stdout)?;
137
138 eprintln!("whoami -> {}", stdout);
139
140 let res = channel.get_exit_status();
141 eprintln!("exit status: {:?}", res);
142
143 Ok(())
144}