Remove the code for the old schema. As the only user of this password manager I don't need to worry about backwards compatibility.

This commit is contained in:
Tom Alexander 2019-07-25 13:39:05 -04:00
parent 2bd0c77bdc
commit b89b4ed329
No known key found for this signature in database
GPG Key ID: 76046DA92D2604F7
3 changed files with 1 additions and 181 deletions

129
src/db.rs
View File

@ -1,6 +1,6 @@
use super::crypt; use super::crypt;
use crate::crypt::EncryptedValue; use crate::crypt::EncryptedValue;
use rusqlite::{params, Connection, NO_PARAMS}; use rusqlite::{params, Connection};
use rustc_serialize::base64; use rustc_serialize::base64;
use rustc_serialize::base64::{FromBase64, ToBase64}; use rustc_serialize::base64::{FromBase64, ToBase64};
use std::error::Error; use std::error::Error;
@ -18,14 +18,6 @@ struct DbProperty {
value: Option<String>, value: Option<String>,
} }
#[derive(Debug)]
pub struct Account {
pub id: i64,
pub host: String,
pub user: String,
pub password: String,
}
pub struct DbNamespace { pub struct DbNamespace {
pub id: i64, pub id: i64,
pub name: EncryptedValue, pub name: EncryptedValue,
@ -197,123 +189,4 @@ impl DbHandle {
let b64value: String = value.to_base64(base64::STANDARD); let b64value: String = value.to_base64(base64::STANDARD);
self.set_db_property(name, &b64value); 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
}
pub fn write_encrypted_value(&mut self, val: EncryptedValue) -> i64 {
let b64ciphertext: String = val.ciphertext.to_base64(base64::STANDARD);
let b64iv: String = val.iv.to_base64(base64::STANDARD);
let b64mac: String = val.mac.code().to_base64(base64::STANDARD);
let tx = self.conn.transaction().unwrap();
tx.execute(
"INSERT INTO encrypted_values (iv, ciphertext, mac) VALUES ($1, $2, $3)",
&[&b64iv, &b64ciphertext, &b64mac],
)
.unwrap();
let rowid: i64 = tx.last_insert_rowid();
let _ = tx.commit().unwrap();
rowid
}
pub fn write_account(
&mut self,
host: EncryptedValue,
username: EncryptedValue,
password: EncryptedValue,
) -> i64 {
// TODO: This should be a transaction
let host_id = self.write_encrypted_value(host);
let user_id = self.write_encrypted_value(username);
let password_id = self.write_encrypted_value(password);
self.conn
.execute(
"INSERT INTO accounts (server, user, password) VALUES ($1, $2, $3)",
&[&host_id, &user_id, &password_id],
)
.unwrap();
self.conn.last_insert_rowid()
}
pub fn delete_account_with_host(&mut self, master_key: [u8; 32], host: &str) {
let accounts: Vec<Account> = self.list_accounts(master_key);
let tx = self.conn.transaction().unwrap();
for account in accounts {
if account.host == host {
tx.execute(
"DELETE FROM encrypted_values WHERE exists \
(SELECT 1 FROM accounts WHERE \
(accounts.server = encrypted_values.id OR \
accounts.user = encrypted_values.id OR \
accounts.password = encrypted_values.id) AND \
accounts.id=$1);",
&[&account.id],
)
.unwrap();
tx.execute("DELETE FROM accounts WHERE id=$1;", &[&account.id])
.unwrap();
}
}
let _ = tx.commit().unwrap();
}
}
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
} }

View File

@ -1,29 +1,10 @@
PRAGMA foreign_keys = ON; PRAGMA foreign_keys = ON;
CREATE TABLE IF NOT EXISTS encrypted_values (
id INTEGER PRIMARY KEY AUTOINCREMENT,
iv TEXT,
ciphertext TEXT,
mac TEXT
);
CREATE TABLE IF NOT EXISTS props( CREATE TABLE IF NOT EXISTS props(
name TEXT NOT NULL PRIMARY KEY, name TEXT NOT NULL PRIMARY KEY,
value TEXT value TEXT
); );
CREATE TABLE IF NOT EXISTS encrypted_props(
name TEXT NOT NULL PRIMARY KEY,
encrypted_value INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS accounts(
id INTEGER PRIMARY KEY AUTOINCREMENT,
server INTEGER NOT NULL,
user INTEGER NOT NULL,
password INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS namespaces( CREATE TABLE IF NOT EXISTS namespaces(
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
name BLOB NOT NULL name BLOB NOT NULL

View File

@ -21,7 +21,6 @@ Usage:
foil set [--namespace=<ns>] [--db=<db>] foil set [--namespace=<ns>] [--db=<db>]
foil get [--namespace=<ns>] [--db=<db>] foil get [--namespace=<ns>] [--db=<db>]
foil list [--namespace=<ns>] [--db=<db>] foil list [--namespace=<ns>] [--db=<db>]
foil transfer [--namespace=<ns>] [--db=<db>] [--src=<db>]
foil dump [--db=<db>] foil dump [--db=<db>]
foil generate <spec> foil generate <spec>
foil (-h | --help) foil (-h | --help)
@ -40,7 +39,6 @@ struct Args {
cmd_get: bool, cmd_get: bool,
cmd_list: bool, cmd_list: bool,
cmd_generate: bool, cmd_generate: bool,
cmd_transfer: bool,
cmd_dump: bool, cmd_dump: bool,
flag_db: Option<String>, flag_db: Option<String>,
flag_src: Option<String>, flag_src: Option<String>,
@ -158,28 +156,6 @@ fn dump(mut db_conn: db::DbHandle, master_key: [u8; 32]) {
} }
} }
fn transfer(
mut db_conn_src: db::DbHandle,
mut db_conn_dest: db::DbHandle,
master_key_src: [u8; 32],
master_key_dest: [u8; 32],
namespace: &str,
) {
for account in db_conn_src.list_accounts(master_key_src).into_iter() {
let new_note = db::Note {
id: 0,
namespace: namespace.to_string(),
category: "account".to_owned(),
title: account.host,
value: format!(
"username: {}\npassword: {}\n",
account.user, account.password
),
};
db_conn_dest.write_note(master_key_dest, new_note);
}
}
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
pretty_env_logger::init(); pretty_env_logger::init();
let args: Args = Docopt::new(USAGE) let args: Args = Docopt::new(USAGE)
@ -202,16 +178,6 @@ fn main() -> Result<(), Box<dyn Error>> {
get(db_conn, master_key, &args.flag_namespace); get(db_conn, master_key, &args.flag_namespace);
} else if args.cmd_list { } else if args.cmd_list {
list(db_conn, master_key, &args.flag_namespace); list(db_conn, master_key, &args.flag_namespace);
} else if args.cmd_transfer {
let mut db_conn_src: db::DbHandle = db::DbHandle::new(&args.flag_src);
let master_key_src: [u8; 32] = get_master_key(&mut db_conn_src);
transfer(
db_conn_src,
db_conn,
master_key_src,
master_key,
&args.flag_namespace,
);
} else if args.cmd_dump { } else if args.cmd_dump {
dump(db_conn, master_key); dump(db_conn, master_key);
} }