summaryrefslogtreecommitdiffstats
path: root/src/bin/client/repl.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/bin/client/repl.rs57
1 files changed, 46 insertions, 11 deletions
diff --git a/src/bin/client/repl.rs b/src/bin/client/repl.rs
index 9af4ea9..d973596 100644
--- a/src/bin/client/repl.rs
+++ b/src/bin/client/repl.rs
@@ -245,7 +245,19 @@ impl ClientState {
245 Effect::ForgetHost(target) => { 245 Effect::ForgetHost(target) => {
246 self.commit_prompt_line(); 246 self.commit_prompt_line();
247 match database::forget_host(&self.conn, &target) { 247 match database::forget_host(&self.conn, &target) {
248 Ok(_) => println!("Cleared trust and stored credentials for {}.", target), 248 Ok(outcome) if outcome.credentials_removed => println!(
249 "Cleared trust and stored credentials for {}.",
250 target
251 ),
252 Ok(outcome) => {
253 println!("Cleared trust for {}.", target);
254 if !outcome.siblings.is_empty() {
255 println!(
256 "Stored credentials kept: this server is still reachable as {}.",
257 outcome.siblings.join(", ")
258 );
259 }
260 }
249 Err(error) => println!("Failed to forget host: {}", error), 261 Err(error) => println!("Failed to forget host: {}", error),
250 } 262 }
251 } 263 }
@@ -506,12 +518,17 @@ impl ClientState {
506 let response = response.trim(); 518 let response = response.trim();
507 519
508 if response.starts_with("OK") { 520 if response.starts_with("OK") {
509 if let Some(addr) = &self.addr { 521 match self.trusted_identity() {
510 if let Err(error) = 522 Some(identity) => {
511 database::save_credentials(&self.conn, addr, &username, &hashed) 523 if let Err(error) =
512 { 524 database::save_credentials(&self.conn, &identity, &username, &hashed)
513 println!("Failed to save credentials: {}", error); 525 {
526 println!("Failed to save credentials: {}", error);
527 }
514 } 528 }
529 None => println!(
530 "Credentials not saved: no verified certificate identity for this host."
531 ),
515 } 532 }
516 self.core.set_logged_in(Some(username.clone())); 533 self.core.set_logged_in(Some(username.clone()));
517 println!("Logged in as {}", username); 534 println!("Logged in as {}", username);
@@ -567,14 +584,27 @@ impl ClientState {
567 return; 584 return;
568 } 585 }
569 let hashed = format!("{:x}", Sha256::digest(password.as_bytes())); 586 let hashed = format!("{:x}", Sha256::digest(password.as_bytes()));
570 if let Some(addr) = &self.addr { 587 let Some(identity) = self.trusted_identity() else {
571 match database::save_credentials(&self.conn, addr, &username, &hashed) { 588 println!(
572 Ok(_) => println!("Credentials saved for {}", addr), 589 "No verified certificate for this host. Connect first so its key can be trusted."
573 Err(error) => println!("Failed to save credentials: {}", error), 590 );
574 } 591 return;
592 };
593 match database::save_credentials(&self.conn, &identity, &username, &hashed) {
594 Ok(_) => println!(
595 "Credentials saved for server {} (every address with this key).",
596 short_fingerprint(&identity)
597 ),
598 Err(error) => println!("Failed to save credentials: {}", error),
575 } 599 }
576 } 600 }
577 601
602 /// Certificate identity of the current address, once it has been verified.
603 fn trusted_identity(&self) -> Option<String> {
604 let addr = self.addr.as_deref()?;
605 database::get_fingerprint(&self.conn, addr)
606 }
607
578 fn list_hosts(&mut self) { 608 fn list_hosts(&mut self) {
579 let hosts = database::get_all_hosts(&self.conn); 609 let hosts = database::get_all_hosts(&self.conn);
580 for line in host_lines(&hosts) { 610 for line in host_lines(&hosts) {
@@ -583,6 +613,11 @@ impl ClientState {
583 } 613 }
584} 614}
585 615
616/// First few hex characters of a fingerprint, enough to tell servers apart.
617fn short_fingerprint(fingerprint: &str) -> String {
618 fingerprint.chars().take(16).collect()
619}
620
586fn style_roulette_number(text: &str, number: u8) -> String { 621fn style_roulette_number(text: &str, number: u8) -> String {
587 match roulette_color(number) { 622 match roulette_color(number) {
588 "red" => text.red().to_string(), 623 "red" => text.red().to_string(),