Password authentication
In this chapter, we will authenticate to the SSH server using a password.
Public key authentication, which is described in the next chapter, is considered more secure than password authentication and should be preferred whenever possible, especially if you cannot securely verify the public key of the server that you are connecting to.
Handle client events in a task
In the previous chapter, we spawned a task to poll the ClientFuture
and we waited for ClientEvent
-s from the ClientReceiver
on the main task. However, from now on, we will need the main task to invoke operations on the Client
, so we start by moving the event handling from the main task to another spawned task:
// Do not handle the client events on the main task
/*
loop {
// Wait for the next event.
let event = client_rx.recv().await
.expect("Error while receiving client event");
...
}
*/
// Instead, spawn another Tokio task to handle the client events.
tokio::task::spawn(async move {
loop {
// Wait for the next event.
let event = client_rx.recv().await
.expect("Error while receiving client event");
... // Handle the events as before
}
});
Authenticate
Back on the main task, we can now call the Client::auth_password()
method to attempt password authentication using username “alice” and password “alicealice”:
// Try to authenticate using a password.
let auth_res = client.auth_password("alice".into(), "alicealice".into()).await
.expect("Error when trying to authenticate");
The method returns an AuthPasswordResult
, which has these variants:
Success
means that we are now authenticated.Failure
means that the server has not accepted the authentication and provided anAuthFailure
with details.ChangePassword
means that the password was correct, but we need to change the password to a new one. The SSH specification provides a mechanism for changing the password, but I have not found any SSH server or client that implements this feature, so Makiko does not support it either. This means that we don’t need to handle theChangePassword
variant in practice, so we treat it as an error.
In this tutorial, we can simply print a message on success and panic on failure:
// Deal with all possible outcomes of password authentication.
match auth_res {
makiko::AuthPasswordResult::Success => {
println!("We have successfully authenticated using a password");
},
makiko::AuthPasswordResult::ChangePassword(prompt) => {
panic!("The server asks us to change password: {:?}", prompt);
},
makiko::AuthPasswordResult::Failure(failure) => {
panic!("The server rejected authentication: {:?}", failure);
}
}
Full code for this tutorial can be found in examples/tutorial_2.rs
. The program will print a message if the authentication was successful, or an error if it failed. If you don’t use the example server for this tutorial, you may need to change the code to use a different username and password.