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:
parent
970e4a8e64
commit
b59893fd9f
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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");
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user