summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-05-24 14:01:28 +0200
committerJustus Winter <justus@sequoia-pgp.org>2019-05-24 16:20:49 +0200
commite97befc021e3e66b554cdd698a37ca80d9d88e44 (patch)
tree8b6dd1ca81d956a5b3f5900af65f62a0e9fa7b8f
parent6502a9ef8e4d2247f5149efcd72f5ba10332ffe5 (diff)
store-rusqlite: Provide wrapper for TPK.
-rw-r--r--Cargo.lock1
-rw-r--r--store-rusqlite/Cargo.toml1
-rw-r--r--store-rusqlite/src/lib.rs47
-rw-r--r--store/src/backend/mod.rs37
4 files changed, 66 insertions, 20 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3cdca9ed..37a135fe 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1684,6 +1684,7 @@ name = "sequoia-store-rusqlite"
version = "0.7.0"
dependencies = [
"rusqlite 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sequoia-openpgp 0.7.0",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
diff --git a/store-rusqlite/Cargo.toml b/store-rusqlite/Cargo.toml
index 0d52c5fd..2f214c3e 100644
--- a/store-rusqlite/Cargo.toml
+++ b/store-rusqlite/Cargo.toml
@@ -21,5 +21,6 @@ default = ["background-services"]
background-services = []
[dependencies]
+sequoia-openpgp = { path = "../openpgp", version = "0.7" }
rusqlite = "0.14"
time = "0.1.38"
diff --git a/store-rusqlite/src/lib.rs b/store-rusqlite/src/lib.rs
index c260e364..39b3a50b 100644
--- a/store-rusqlite/src/lib.rs
+++ b/store-rusqlite/src/lib.rs
@@ -1,5 +1,8 @@
//! Data types for working with `rusqlite`.
+extern crate sequoia_openpgp as openpgp;
+use openpgp::{parse::Parse, serialize::Serialize};
+
extern crate rusqlite;
use rusqlite::types::{ToSql, ToSqlOutput, FromSql, FromSqlResult, ValueRef};
use std::fmt;
@@ -94,3 +97,47 @@ impl Sub<Timestamp> for Timestamp {
self.0 - other.0
}
}
+
+/// Represents a TPK.
+#[derive(Clone, PartialEq)]
+pub struct TPK(openpgp::TPK);
+
+impl fmt::Display for TPK {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.0)
+ }
+}
+
+impl From<openpgp::TPK> for TPK {
+ fn from(tpk: openpgp::TPK) -> Self {
+ TPK(tpk)
+ }
+}
+
+impl From<TPK> for openpgp::TPK {
+ fn from(tpk: TPK) -> Self {
+ tpk.0
+ }
+}
+
+impl ToSql for TPK {
+ fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
+ use rusqlite::Error;
+
+ let mut buf = Vec::new();
+ self.0.serialize(&mut buf)
+ .map_err(|e| Error::ToSqlConversionFailure(Box::new(e.compat())))?;
+
+ Ok(buf.into())
+ }
+}
+
+impl FromSql for TPK {
+ fn column_result(value: ValueRef) -> FromSqlResult<Self> {
+ use rusqlite::types::FromSqlError;
+
+ Ok(openpgp::TPK::from_bytes(value.as_blob()?)
+ .map_err(|e| FromSqlError::Other(Box::new(e.compat())))?
+ .into())
+ }
+}
diff --git a/store/src/backend/mod.rs b/store/src/backend/mod.rs
index d04ac296..4ee445cd 100644
--- a/store/src/backend/mod.rs
+++ b/store/src/backend/mod.rs
@@ -547,23 +547,20 @@ impl node::binding::Server for BindingServer {
// Check in the database for the current key.
let key_id = sry!(self.key_id());
- let (fingerprint, key): (String, Option<Vec<u8>>)
+ let (fingerprint, current): (String, Option<TPK>)
= sry!(self.c.query_row(
"SELECT fingerprint, key FROM keys WHERE id = ?1",
&[&key_id],
- |row| (row.get(0), row.get_checked(1).ok())));
+ |row| (row.get(0), row.get_checked::<_, store_rusqlite::TPK>(1)
+ .map(|t| TPK::from(t)).ok())));
- // If we found one, convert it to TPK.
- let current = if let Some(current) = key {
- let current = sry!(TPK::from_bytes(&current));
+ // If we found one, check consistency.
+ if let Some(current) = current.as_ref() {
if current.fingerprint().to_hex() != fingerprint {
// Inconsistent database.
fail!(node::Error::SystemError);
}
- Some(current)
- } else {
- None
- };
+ }
// Check for conflicts.
if new.fingerprint().to_hex() != fingerprint {
@@ -754,20 +751,19 @@ impl KeyServer {
/// Merges other into this key updating the database.
///
/// Returnes the merged key as blob.
- fn merge(&self, other: TPK) -> Result<Vec<u8>> {
+ fn merge(&self, other: TPK) -> Result<TPK> {
let mut new = other;
// Get the current key from the database.
- let (fingerprint, key): (String, Option<Vec<u8>>)
+ let (fingerprint, key): (String, Option<TPK>)
= self.c.query_row(
"SELECT fingerprint, key FROM keys WHERE id = ?1",
&[&self.id],
- |row| (row.get(0), row.get_checked(1).ok()))?;
+ |row| (row.get(0), row.get_checked::<_, store_rusqlite::TPK>(1)
+ .map(|t| t.into()).ok()))?;
// If there was a key stored there, merge it.
if let Some(current) = key {
- let current = TPK::from_bytes(&current)?;
-
if current.fingerprint().to_hex() != fingerprint {
// Inconsistent database.
return Err(node::Error::SystemError.into());
@@ -781,14 +777,13 @@ impl KeyServer {
}
// Write key back to the database.
- let mut blob = vec![];
- new.serialize(&mut blob)?;
-
+ let new = store_rusqlite::TPK::from(new);
self.c.execute("UPDATE keys SET key = ?1 WHERE id = ?2",
- &[&blob, &self.id])?;
+ &[&new, &self.id])?;
+ let new = new.into();
KeyServer::reindex_subkeys(&self.c, self.id, &new)?;
- Ok(blob)
+ Ok(new)
}
/// Keeps the mapping of (sub)KeyIDs to keys up-to-date.
@@ -1030,7 +1025,9 @@ impl node::key::Server for KeyServer {
-> Promise<(), capnp::Error> {
bind_results!(results);
let new = sry!(TPK::from_bytes(&pry!(pry!(params.get()).get_key())));
- let blob = sry!(self.merge(new));
+ let tpk = sry!(self.merge(new));
+ let mut blob = Vec::new();
+ sry!(tpk.serialize(&mut blob));
pry!(pry!(results.get().get_result()).set_ok(&blob[..]));
Promise::ok(())
}