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 crate::crypt::EncryptedValue;
use rusqlite::{params, Connection, NO_PARAMS};
use rusqlite::{params, Connection};
use rustc_serialize::base64;
use rustc_serialize::base64::{FromBase64, ToBase64};
use std::error::Error;
@ -18,14 +18,6 @@ struct DbProperty {
value: Option<String>,
}
#[derive(Debug)]
pub struct Account {
pub id: i64,
pub host: String,
pub user: String,
pub password: String,
}
pub struct DbNamespace {
pub id: i64,
pub name: EncryptedValue,
@ -197,123 +189,4 @@ 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
}
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;
CREATE TABLE IF NOT EXISTS encrypted_values (
id INTEGER PRIMARY KEY AUTOINCREMENT,
iv TEXT,
ciphertext TEXT,
mac TEXT
);
CREATE TABLE IF NOT EXISTS props(
name TEXT NOT NULL PRIMARY KEY,
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(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name BLOB NOT NULL

View File

@ -21,7 +21,6 @@ Usage:
foil set [--namespace=<ns>] [--db=<db>]
foil get [--namespace=<ns>] [--db=<db>]
foil list [--namespace=<ns>] [--db=<db>]
foil transfer [--namespace=<ns>] [--db=<db>] [--src=<db>]
foil dump [--db=<db>]
foil generate <spec>
foil (-h | --help)
@ -40,7 +39,6 @@ struct Args {
cmd_get: bool,
cmd_list: bool,
cmd_generate: bool,
cmd_transfer: bool,
cmd_dump: bool,
flag_db: 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>> {
pretty_env_logger::init();
let args: Args = Docopt::new(USAGE)
@ -202,16 +178,6 @@ fn main() -> Result<(), Box<dyn Error>> {
get(db_conn, master_key, &args.flag_namespace);
} else if args.cmd_list {
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 {
dump(db_conn, master_key);
}