|
|
|
@ -1,4 +1,5 @@
|
|
|
|
|
use rusqlite::Connection;
|
|
|
|
|
use super::crypt;
|
|
|
|
|
use rusqlite::{Connection, NO_PARAMS};
|
|
|
|
|
use rustc_serialize::base64;
|
|
|
|
|
use rustc_serialize::base64::{FromBase64, ToBase64};
|
|
|
|
|
use std::error::Error;
|
|
|
|
@ -16,6 +17,14 @@ struct DbProperty {
|
|
|
|
|
value: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct Account {
|
|
|
|
|
pub id: i64,
|
|
|
|
|
pub host: String,
|
|
|
|
|
pub user: String,
|
|
|
|
|
pub password: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl DbHandle {
|
|
|
|
|
pub fn new(db_path: &Option<String>) -> DbHandle {
|
|
|
|
|
let path: PathBuf = db_path
|
|
|
|
@ -25,7 +34,7 @@ impl DbHandle {
|
|
|
|
|
let mut conn: Connection = Connection::open(path).unwrap();
|
|
|
|
|
let tx = conn.transaction().unwrap();
|
|
|
|
|
tx.execute_batch(DB_INIT_QUERY).unwrap();
|
|
|
|
|
tx.commit();
|
|
|
|
|
tx.commit().unwrap();
|
|
|
|
|
DbHandle { conn: conn }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -65,4 +74,65 @@ impl DbHandle {
|
|
|
|
|
let b64value: String = value.to_base64(base64::STANDARD);
|
|
|
|
|
self.set_db_property(name, &b64value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn list_accounts(&mut self, master_key: [u8; 32]) -> Vec<Account> {
|
|
|
|
|
let mut stmt = self.conn
|
|
|
|
|
.prepare("SELECT h.iv, h.ciphertext, h.mac, u.iv, u.ciphertext, u.mac, p.iv, p.ciphertext, p.mac, a.id FROM accounts a \
|
|
|
|
|
LEFT JOIN encrypted_values h ON a.server=h.id \
|
|
|
|
|
LEFT JOIN encrypted_values u ON a.user=u.id \
|
|
|
|
|
LEFT JOIN encrypted_values p ON a.password=p.id")
|
|
|
|
|
.unwrap();
|
|
|
|
|
let result: Vec<Account> = {
|
|
|
|
|
let props = stmt
|
|
|
|
|
.query_map(NO_PARAMS, |row| {
|
|
|
|
|
let host: String = String::from_utf8(decrypt_base64(
|
|
|
|
|
row.get(0).unwrap(),
|
|
|
|
|
row.get(1).unwrap(),
|
|
|
|
|
row.get(2).unwrap(),
|
|
|
|
|
master_key,
|
|
|
|
|
))
|
|
|
|
|
.unwrap();
|
|
|
|
|
let user: String = String::from_utf8(decrypt_base64(
|
|
|
|
|
row.get(3).unwrap(),
|
|
|
|
|
row.get(4).unwrap(),
|
|
|
|
|
row.get(5).unwrap(),
|
|
|
|
|
master_key,
|
|
|
|
|
))
|
|
|
|
|
.unwrap();
|
|
|
|
|
let password: String = String::from_utf8(decrypt_base64(
|
|
|
|
|
row.get(6).unwrap(),
|
|
|
|
|
row.get(7).unwrap(),
|
|
|
|
|
row.get(8).unwrap(),
|
|
|
|
|
master_key,
|
|
|
|
|
))
|
|
|
|
|
.unwrap();
|
|
|
|
|
Ok(Account {
|
|
|
|
|
id: row.get(9).unwrap(),
|
|
|
|
|
host: host,
|
|
|
|
|
user: user,
|
|
|
|
|
password: password,
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
props.map(move |x| x.unwrap()).collect()
|
|
|
|
|
};
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn decrypt_base64(iv: String, ciphertext: String, mac: String, master_key: [u8; 32]) -> Vec<u8> {
|
|
|
|
|
let mut iv_bytes: [u8; 32] = [0; 32];
|
|
|
|
|
let mut mac_bytes: [u8; 32] = [0; 32];
|
|
|
|
|
|
|
|
|
|
iv_bytes.clone_from_slice(&iv.from_base64().unwrap());
|
|
|
|
|
mac_bytes.clone_from_slice(&mac.from_base64().unwrap());
|
|
|
|
|
|
|
|
|
|
let decrypted: Vec<u8> = crypt::decrypt_value(
|
|
|
|
|
ciphertext.from_base64().unwrap(),
|
|
|
|
|
master_key,
|
|
|
|
|
iv_bytes,
|
|
|
|
|
mac_bytes,
|
|
|
|
|
);
|
|
|
|
|
decrypted
|
|
|
|
|
}
|
|
|
|
|