Use SQLITE3 as Server Certificate Database backend
This commit is contained in:
@@ -27,6 +27,7 @@ rand = "0.8.5"
|
|||||||
uuid = { version = "1.7.0", features = ["v4", "serde"] }
|
uuid = { version = "1.7.0", features = ["v4", "serde"] }
|
||||||
rustls-pemfile = "2.0.0"
|
rustls-pemfile = "2.0.0"
|
||||||
x509-parser = "0.16.0"
|
x509-parser = "0.16.0"
|
||||||
|
rusqlite = { version = "0.31.0", features = ["bundled"] }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "init_certs"
|
name = "init_certs"
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ async fn main() {
|
|||||||
let server_ca = CACertPair::load_from_file("certs_pem/server_root_ca.pem").unwrap();
|
let server_ca = CACertPair::load_from_file("certs_pem/server_root_ca.pem").unwrap();
|
||||||
let guestserver_ca = CACertPair::load_from_file("certs_pem/guestserver_root_ca.pem").unwrap();
|
let guestserver_ca = CACertPair::load_from_file("certs_pem/guestserver_root_ca.pem").unwrap();
|
||||||
// Load Actors
|
// Load Actors
|
||||||
let servercert_db = ServerCertDB::new().start();
|
let servercert_db = ServerCertDB::new("certsdb.sqlite").unwrap().start();
|
||||||
let dataconn_manager = DataConnManager::new().start();
|
let dataconn_manager = DataConnManager::new().start();
|
||||||
let pendingdataconn_manager = PendingDataConnManager::new(dataconn_manager).start();
|
let pendingdataconn_manager = PendingDataConnManager::new(dataconn_manager).start();
|
||||||
let server_manager = ServerManager::new(pendingdataconn_manager.clone()).start();
|
let server_manager = ServerManager::new(pendingdataconn_manager.clone()).start();
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
use std::collections::HashMap;
|
use std::path::Path;
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
|
use rusqlite::{Connection};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum DBError {
|
pub enum DBError {
|
||||||
#[error("Certificate is already registered with name {0}")]
|
#[error("Certificate is already registered with name {0}")]
|
||||||
CertAlreadyRegistered(String),
|
CertAlreadyRegistered(String),
|
||||||
// #[error("Generic Failure")]
|
#[error("Generic Failure")]
|
||||||
// GenericFailure,
|
GenericFailure,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
@@ -35,14 +36,29 @@ pub struct FetchName {
|
|||||||
pub cert: Vec<u8>,
|
pub cert: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move into Sqlite DB with unique check on col1 and col2!!!! Right now name is not unique
|
fn init_db(conn: Connection) -> rusqlite::Result<Connection> {
|
||||||
|
conn.execute(
|
||||||
|
"CREATE TABLE IF NOT EXISTS servercert (
|
||||||
|
cert BLOB PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL
|
||||||
|
)",
|
||||||
|
(), // empty list of parameters.
|
||||||
|
)?;
|
||||||
|
Ok(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Right now name is not unique. Consider making it unique and checking it for duplication
|
||||||
pub struct ServerCertDB {
|
pub struct ServerCertDB {
|
||||||
db: HashMap<Vec<u8>, String>, // Cert to Name
|
conn: Connection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerCertDB {
|
impl ServerCertDB {
|
||||||
pub fn new() -> Self {
|
fn new_in_memory() -> rusqlite::Result<Self> {
|
||||||
ServerCertDB { db: HashMap::new() }
|
Ok(ServerCertDB { conn: init_db(Connection::open_in_memory()?)? })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new<P: AsRef<Path>>(path: P) -> rusqlite::Result<Self> {
|
||||||
|
Ok(ServerCertDB { conn: init_db(Connection::open(path)?)? })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,13 +70,23 @@ impl Handler<RegisterServer> for ServerCertDB {
|
|||||||
type Result = Result<(), DBError>;
|
type Result = Result<(), DBError>;
|
||||||
|
|
||||||
fn handle(&mut self, msg: RegisterServer, _ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: RegisterServer, _ctx: &mut Self::Context) -> Self::Result {
|
||||||
match self.db.get(&msg.cert) {
|
match self.conn.query_row(
|
||||||
None => {
|
"SELECT name FROM servercert WHERE cert = ?1",
|
||||||
self.db.insert(msg.cert, msg.name);
|
(&msg.cert,),
|
||||||
|
|row| row.get::<_, String>(0)
|
||||||
|
) {
|
||||||
|
Ok(name) => {
|
||||||
|
Err(DBError::CertAlreadyRegistered(name))
|
||||||
|
}
|
||||||
|
Err(rusqlite::Error::QueryReturnedNoRows) => {
|
||||||
|
self.conn.execute(
|
||||||
|
"INSERT INTO servercert (cert, name) VALUES (?1, ?2)",
|
||||||
|
(&msg.cert, &msg.name)
|
||||||
|
).map_err(|_| DBError::GenericFailure)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Some(name) => {
|
Err(_) => {
|
||||||
Err(DBError::CertAlreadyRegistered(name.clone()))
|
Err(DBError::GenericFailure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +96,12 @@ impl Handler<IsNameRegistered> for ServerCertDB {
|
|||||||
type Result = bool;
|
type Result = bool;
|
||||||
|
|
||||||
fn handle(&mut self, msg: IsNameRegistered, _ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: IsNameRegistered, _ctx: &mut Self::Context) -> Self::Result {
|
||||||
self.db.values().any(|x| *x == msg.name)
|
let count: u64 = self.conn.query_row(
|
||||||
|
"SELECT COUNT(*) FROM servercert WHERE name = ?1",
|
||||||
|
(&msg.name,),
|
||||||
|
|row| row.get(0)
|
||||||
|
).unwrap();
|
||||||
|
count > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +109,21 @@ impl Handler<FetchName> for ServerCertDB {
|
|||||||
type Result = Option<String>;
|
type Result = Option<String>;
|
||||||
|
|
||||||
fn handle(&mut self, msg: FetchName, _ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: FetchName, _ctx: &mut Self::Context) -> Self::Result {
|
||||||
self.db.get(&msg.cert).map(|s| s.to_owned())
|
match self.conn.query_row(
|
||||||
|
"SELECT name FROM servercert WHERE cert = ?1",
|
||||||
|
(&msg.cert,),
|
||||||
|
|row| row.get(0)
|
||||||
|
) {
|
||||||
|
Ok(name) => {
|
||||||
|
Some(name)
|
||||||
|
}
|
||||||
|
Err(rusqlite::Error::QueryReturnedNoRows) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
panic!("Error during FetchName: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +131,25 @@ impl Handler<UnregisterServer> for ServerCertDB {
|
|||||||
type Result = Option<String>;
|
type Result = Option<String>;
|
||||||
|
|
||||||
fn handle(&mut self, msg: UnregisterServer, _ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: UnregisterServer, _ctx: &mut Self::Context) -> Self::Result {
|
||||||
self.db.remove(&msg.cert)
|
match self.conn.query_row(
|
||||||
|
"SELECT name FROM servercert WHERE cert = ?1",
|
||||||
|
(&msg.cert,),
|
||||||
|
|row| row.get::<_, String>(0)
|
||||||
|
) {
|
||||||
|
Ok(name) => {
|
||||||
|
self.conn.execute(
|
||||||
|
"DELETE FROM servercert WHERE cert = ?1",
|
||||||
|
(&msg.cert,)
|
||||||
|
).unwrap();
|
||||||
|
Some(name)
|
||||||
|
}
|
||||||
|
Err(rusqlite::Error::QueryReturnedNoRows) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
panic!("Error during UnregisterServer: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,13 +159,13 @@ mod tests {
|
|||||||
|
|
||||||
#[actix::test]
|
#[actix::test]
|
||||||
async fn emptydb_isnameregistered() {
|
async fn emptydb_isnameregistered() {
|
||||||
let servercert_db = ServerCertDB::new().start();
|
let servercert_db = ServerCertDB::new_in_memory().unwrap().start();
|
||||||
assert!(!servercert_db.send(IsNameRegistered { name: "test".into() }).await.unwrap());
|
assert!(!servercert_db.send(IsNameRegistered { name: "test".into() }).await.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix::test]
|
#[actix::test]
|
||||||
async fn emptyvec() {
|
async fn emptyvec() {
|
||||||
let servercert_db = ServerCertDB::new().start();
|
let servercert_db = ServerCertDB::new_in_memory().unwrap().start();
|
||||||
assert!(servercert_db.send(RegisterServer { cert: vec![], name: "test".into() }).await.unwrap().is_ok());
|
assert!(servercert_db.send(RegisterServer { cert: vec![], name: "test".into() }).await.unwrap().is_ok());
|
||||||
assert!(servercert_db.send(IsNameRegistered { name: "test".into() }).await.unwrap());
|
assert!(servercert_db.send(IsNameRegistered { name: "test".into() }).await.unwrap());
|
||||||
assert_eq!(servercert_db.send(FetchName { cert: vec![] }).await.unwrap().unwrap(), "test");
|
assert_eq!(servercert_db.send(FetchName { cert: vec![] }).await.unwrap().unwrap(), "test");
|
||||||
@@ -114,7 +177,7 @@ mod tests {
|
|||||||
|
|
||||||
#[actix::test]
|
#[actix::test]
|
||||||
async fn normalcert() {
|
async fn normalcert() {
|
||||||
let servercert_db = ServerCertDB::new().start();
|
let servercert_db = ServerCertDB::new_in_memory().unwrap().start();
|
||||||
let cert = vec![112, 111, 114, 99, 111, 100, 105, 111];
|
let cert = vec![112, 111, 114, 99, 111, 100, 105, 111];
|
||||||
assert!(servercert_db.send(RegisterServer { cert: cert.clone(), name: "test2".into() }).await.unwrap().is_ok());
|
assert!(servercert_db.send(RegisterServer { cert: cert.clone(), name: "test2".into() }).await.unwrap().is_ok());
|
||||||
assert!(servercert_db.send(IsNameRegistered { name: "test2".into() }).await.unwrap());
|
assert!(servercert_db.send(IsNameRegistered { name: "test2".into() }).await.unwrap());
|
||||||
@@ -127,7 +190,7 @@ mod tests {
|
|||||||
|
|
||||||
#[actix::test]
|
#[actix::test]
|
||||||
async fn cert2_remains_after_delete_cert1() {
|
async fn cert2_remains_after_delete_cert1() {
|
||||||
let servercert_db = ServerCertDB::new().start();
|
let servercert_db = ServerCertDB::new_in_memory().unwrap().start();
|
||||||
let cert1 = vec![112, 111, 114, 99, 111, 100, 105, 111];
|
let cert1 = vec![112, 111, 114, 99, 111, 100, 105, 111];
|
||||||
let cert2 = vec![67, 65, 78, 68, 69, 68, 73, 79];
|
let cert2 = vec![67, 65, 78, 68, 69, 68, 73, 79];
|
||||||
assert!(servercert_db.send(RegisterServer { cert: cert1.clone(), name: "test3".into() }).await.unwrap().is_ok());
|
assert!(servercert_db.send(RegisterServer { cert: cert1.clone(), name: "test3".into() }).await.unwrap().is_ok());
|
||||||
|
|||||||
Reference in New Issue
Block a user