index : bitwarden-ssh-agent.git

ascending towards madness

author holly sparkles <sparkles@holly.sh> 2023-08-01 21:12:02.0 +00:00:00
committer holly sparkles <sparkles@holly.sh> 2023-08-01 21:12:02.0 +00:00:00
commit
36f8f9a9bd23614c7fea302b0aef3e11af75baea [patch]
tree
7a357214dff840a8fb048ae1089b54018df253f9
parent
bebbc93e736b9cc75ade477fac5c7fc147883130
download
36f8f9a9bd23614c7fea302b0aef3e11af75baea.tar.gz

feat: add registering keys with ssh-agent



Diff

 src/main.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 48 insertions(+), 3 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 4fc1059..f9517c8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,6 @@
use std::env;
use std::{env, process::{Command, Stdio}};
use gumdrop::Options;
use anyhow::Result;
use anyhow::{Result, Context};

mod util;
mod bwutil;
@@ -13,6 +13,13 @@ const BW_FIELD_KEY_FILENAME: &str = "private";
const BW_FIELD_KEY_PASSPHRASE: &str = "passphrase";

fn main() -> Result<()> {
	// This environment variable only set when calling ssh-agent, so return the passphrase to authenticate and then quit.
	let unlock_passphrase = env::var(BW_FIELD_KEY_PASSPHRASE);
	if unlock_passphrase.is_ok() {
		println!("{}", unlock_passphrase.unwrap());
		return Ok(())
	}

    let args: util::Cli = util::Cli::parse_args_default_or_exit();
	if args.version {
		println!("{}", &util::get_version_string()?);
@@ -47,7 +54,8 @@ fn main() -> Result<()> {
					if let Some(attachments) = &item.attachments {
						for attachment in attachments {
							if attachment.file_name.eq(&key_filename) {
								println!("{:#?}", item);
								//println!("{:#?}", item);
								let _key = register_key(&item.id, &attachment.id, &key_passphrase, &session_token)?;
							}
						}
					}
@@ -98,3 +106,40 @@ fn check_session_token(args: &util::Cli) -> Result<String> {

	Ok(session_token)
}

fn register_key(item_id: &str, attachment_id: &str, passphrase: &str, session_token: &str) -> Result<()> {
    let bw_command = Command::new("bw")
		.arg("get")
		.arg("attachment")
		.arg(attachment_id)
		.arg("--itemid")
		.arg(item_id)
		.arg("--raw")
		.arg("--session")
		.arg(session_token)
        .stdout(Stdio::piped())
        .spawn()
		.with_context(|| 
			format!("Error running command:\n  `bw get attachment {} --itemid {} --raw --session **REDACTED**`", attachment_id, item_id)
		)?;

	let app_path = env::current_exe()?;
	let app_path = app_path.to_string_lossy().to_string();

    let ssh_command = Command::new("ssh-add")
		.env("SSH_ASKPASS", &app_path)
		.env(BW_FIELD_KEY_PASSPHRASE, passphrase)
        .arg("-")
        .stdin(Stdio::from(bw_command.stdout.unwrap())) // Pipe through.
        .spawn()
		.with_context(|| 
			format!("Error running command:\n  `SSH_ASKPASS=\"{}\" {}=\"{}\"ssh-add -`", app_path, BW_FIELD_KEY_PASSPHRASE, passphrase)
		)?;
    let output = ssh_command.wait_with_output().unwrap();
    let result = String::from_utf8(output.stdout).unwrap();
	if !result.is_empty() {
		println!("{:?}", result);
	}
    
    Ok(())
}
\ No newline at end of file