1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-29 16:42:13 +03:00

ssh: allow a number of auth retries

Rather than just a single attempt at each mechanism, let's allow up
to 3 loops, each time trying all supported mechanisms.  This helps
for the case where the user makes a typo with their password, and
should also help for more complicated auth setups where succeeding
with one mechanism may not be sufficient.

While testing this out I noticed that were deferring closing the
OS level window until after the entire auth attempt, so I added
some logic to proactively close the prompt windows.  In the longer
term I'd like all related prompts to render in the same window
for improved cognotive continuity.
This commit is contained in:
Wez Furlong 2020-01-24 08:39:34 -08:00
parent 970e4a8e64
commit b59893fd9f
4 changed files with 54 additions and 26 deletions

View File

@ -2454,7 +2454,7 @@ impl TermWindow {
let (top, mut lines) = tab.renderer().get_lines(stable_row..stable_row + 1); let (top, mut lines) = tab.renderer().get_lines(stable_row..stable_row + 1);
let new_highlight = if top == stable_row { let new_highlight = if top == stable_row {
let line = &mut lines[0]; if let Some(line) = lines.get_mut(0) {
if let Some(cell) = line.cells().get(x) { if let Some(cell) = line.cells().get(x) {
cell.attrs().hyperlink.as_ref().cloned() cell.attrs().hyperlink.as_ref().cloned()
} else { } else {
@ -2462,6 +2462,9 @@ impl TermWindow {
} }
} else { } else {
None None
}
} else {
None
}; };
match (self.current_highlight.as_ref(), new_highlight) { match (self.current_highlight.as_ref(), new_highlight) {

View File

@ -252,6 +252,11 @@ impl Mux {
} }
} }
pub fn kill_window(&self, window_id: WindowId) {
let mut windows = self.windows.borrow_mut();
windows.remove(&window_id);
}
pub fn get_window(&self, window_id: WindowId) -> Option<Ref<Window>> { pub fn get_window(&self, window_id: WindowId) -> Option<Ref<Window>> {
if !self.windows.borrow().contains_key(&window_id) { if !self.windows.borrow().contains_key(&window_id) {
return None; return None;

View File

@ -281,6 +281,11 @@ pub fn ssh_connect(remote_address: &str, username: &str) -> anyhow::Result<ssh2:
let methods: HashSet<&str> = sess.auth_methods(&username)?.split(',').collect(); let methods: HashSet<&str> = sess.auth_methods(&username)?.split(',').collect();
for _ in 0..3 {
if sess.authenticated() {
break;
}
if !sess.authenticated() && methods.contains("publickey") { if !sess.authenticated() && methods.contains("publickey") {
if let Err(err) = sess.userauth_agent(&username) { if let Err(err) = sess.userauth_agent(&username) {
log::info!("while attempting agent auth: {}", err); log::info!("while attempting agent auth: {}", err);
@ -305,6 +310,7 @@ pub fn ssh_connect(remote_address: &str, username: &str) -> anyhow::Result<ssh2:
log::error!("while attempting keyboard-interactive auth: {}", err); log::error!("while attempting keyboard-interactive auth: {}", err);
} }
} }
}
if !sess.authenticated() { if !sess.authenticated() {
bail!("unable to authenticate session"); bail!("unable to authenticate session");

View File

@ -403,7 +403,7 @@ pub async fn run<
render_rx: Receiver<Vec<Change>>, render_rx: Receiver<Vec<Change>>,
width: usize, width: usize,
height: usize, height: usize,
) -> anyhow::Result<()> { ) -> anyhow::Result<WindowId> {
let mux = Mux::get().unwrap(); let mux = Mux::get().unwrap();
// TODO: make a singleton // TODO: make a singleton
@ -431,16 +431,30 @@ pub async fn run<
let gui = front_end().unwrap(); let gui = front_end().unwrap();
gui.spawn_new_window(&fontconfig, &tab, window_id)?; gui.spawn_new_window(&fontconfig, &tab, window_id)?;
Ok(()) Ok(window_id)
} }
let window_id: WindowId = promise::spawn::spawn_into_main_thread(async move {
register_tab(input_tx, render_rx, width, height).await
})
.await
.unwrap_or_else(|| bail!("task panicked or was cancelled"))?;
let result = promise::spawn::spawn_into_new_thread(move || f(tw_term))
.await
.unwrap_or_else(|| bail!("task panicked or was cancelled"));
// Since we're typically called with an outstanding Activity token active,
// the dead status of the tab will be ignored until after the activity
// resolves. In the case of SSH where (currently!) several prompts may
// be shown in succession, we don't want to leave lingering dead windows
// on the screen so let's ask the mux to kill off our window now.
promise::spawn::spawn_into_main_thread(async move { promise::spawn::spawn_into_main_thread(async move {
register_tab(input_tx, render_rx, width, height).await.ok(); let mux = Mux::get().unwrap();
mux.kill_window(window_id);
}); });
promise::spawn::spawn_into_new_thread(move || f(tw_term)) result
.await
.unwrap_or_else(|| bail!("task panicked or was cancelled"))
} }
pub fn message_box_ok(message: &str) { pub fn message_box_ok(message: &str) {