keystore v2 work

This commit is contained in:
core 2023-08-17 11:22:12 -04:00
parent bafc361e76
commit e901f63bb9
Signed by: core
GPG Key ID: FDBF740DADDCEECF
1 changed files with 47 additions and 41 deletions

View File

@ -17,10 +17,11 @@ use std::time::{SystemTime, UNIX_EPOCH};
use sea_orm::{ActiveModelTrait, EntityTrait}; use sea_orm::{ActiveModelTrait, EntityTrait};
use trifid_pki::cert::{deserialize_ed25519_public, deserialize_x25519_public}; use trifid_pki::cert::{deserialize_ed25519_public, deserialize_x25519_public};
use trifid_pki::x25519_dalek::PublicKey; use trifid_pki::x25519_dalek::PublicKey;
use trifid_api_entities::entity::host; use trifid_api_entities::entity::{host, keystore_entry, keystore_host};
use crate::error::APIErrorsResponse; use crate::error::APIErrorsResponse;
use sea_orm::{ColumnTrait, QueryFilter, IntoActiveModel}; use sea_orm::{ColumnTrait, QueryFilter, IntoActiveModel};
use sea_orm::ActiveValue::Set; use sea_orm::ActiveValue::Set;
use trifid_api_entities::entity::prelude::KeystoreHost;
#[post("/v1/dnclient")] #[post("/v1/dnclient")]
pub async fn dnclient( pub async fn dnclient(
@ -54,8 +55,18 @@ pub async fn dnclient(
} }
}; };
let host_in_ks = keystore.hosts.iter_mut().find(|u| &u.id == host); let host_in_ks = match keystore_host::Entity::find().filter(keystore_host::Column::Id.eq(host)).one(&db.conn).await {
let host_in_ks = match host_in_ks { Ok(maybe_host) => maybe_host,
Err(e) => {
return HttpResponse::InternalServerError().json(vec![APIError {
code: "ERR_DB_ERROR".to_string(),
message: "There was an error finding the keys for your host, please contact your administrator".to_string(),
path: None
}])
}
};
let keystore_header = match host_in_ks {
Some(host) => host, Some(host) => host,
None => { None => {
return HttpResponse::Unauthorized().json(vec![APIError { return HttpResponse::Unauthorized().json(vec![APIError {
@ -63,18 +74,36 @@ pub async fn dnclient(
message: "The host does not exist or you do not have permission to access it." message: "The host does not exist or you do not have permission to access it."
.to_string(), .to_string(),
path: None, path: None,
}]);
}
};
let counter = keystore_header.counter;
// pull their key information
let key_info = match keystore_entry::Entity::find().filter(keystore_entry::Column::Host.eq(&keystore_header.id)).one(&db.conn).await {
Ok(maybe_keys) => maybe_keys,
Err(e) => {
return HttpResponse::InternalServerError().json(vec![APIError {
code: "ERR_DB_ERROR".to_string(),
message: "There was an error finding the keys for your host, please contact your administrator".to_string(),
path: None
}]) }])
} }
}; };
let client_keys = host_in_ks let keystore_data = match key_info {
.client_keys Some(key_info) => key_info,
.iter() None => {
.find(|u| u.id == req.counter as u64); return HttpResponse::Unauthorized().json(vec![APIError {
let client_keys_2 = host_in_ks code: "ERR_HOST_ERROR".to_string(),
.client_keys message: "The host does not exist or you do not have permission to access it."
.iter() .to_string(),
.find(|u| u.id == host_in_ks.current_client_key); path: None,
}]);
}
};
let signature = match Signature::from_slice(&req.signature) { let signature = match Signature::from_slice(&req.signature) {
Ok(sig) => sig, Ok(sig) => sig,
@ -90,27 +119,9 @@ pub async fn dnclient(
} }
}; };
let mut valid = false; let key = VerifyingKey::from(keystore_data.client_signing_key.try_into().unwrap());
let mut valid_key = None;
if let Some(client_keys) = client_keys { if !key.verify(&req.message.as_bytes(), &signature).is_ok() {
if client_keys.ed_pub.verify(req.message.as_bytes(), &signature).is_ok() {
valid = true;
valid_key = Some(client_keys);
}
}
if let Some(client_keys_2) = client_keys_2 {
if client_keys_2.ed_pub.verify(req.message.as_bytes(), &signature).is_ok() {
valid = true;
valid_key = Some(client_keys_2);
}
}
if client_keys.is_none() && client_keys_2.is_none() {
panic!("No valid keys for host {}", host);
}
if !valid {
// Be intentionally vague as the message is invalid. // Be intentionally vague as the message is invalid.
warn!("! invalid signature from {}", host); warn!("! invalid signature from {}", host);
return HttpResponse::Unauthorized().json(vec![APIError { return HttpResponse::Unauthorized().json(vec![APIError {
@ -121,8 +132,6 @@ pub async fn dnclient(
}]); }]);
} }
let client_keys = valid_key.unwrap();
// Sig OK // Sig OK
// Decode the message from base64 // Decode the message from base64
@ -190,7 +199,7 @@ pub async fn dnclient(
// Do a config build // Do a config build
let info = match collect_info(&db, host, client_keys.dh_pub.as_bytes()).await { let info = match collect_info(&db, host, &keystore_data.client_dh_key).await {
Ok(i) => i, Ok(i) => i,
Err(e) => { Err(e) => {
return HttpResponse::InternalServerError().json(EnrollResponse::Error { return HttpResponse::InternalServerError().json(EnrollResponse::Error {
@ -218,13 +227,10 @@ pub async fn dnclient(
} }
}; };
let current_cfg = host_in_ks let current_cfg = keystore_data.config;
.config let generated_config_string = serde_yaml::to_string(&cfg).unwrap();
.iter()
.find(|u| u.id == host_in_ks.current_config);
let config_update_avail = current_cfg.map(|u| u.config.clone()) != Some(cfg.clone()) let config_update_avail = current_cfg != generated_config_string || req.counter < keystore_header.counter as u32;
|| req.counter < host_in_ks.current_config as u32;
host_am.last_out_of_date = Set(config_update_avail); host_am.last_out_of_date = Set(config_update_avail);
host_am.last_seen_at = Set(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64); host_am.last_seen_at = Set(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64);
@ -315,7 +321,7 @@ pub async fn dnclient(
} }
}; };
let ks = host_in_ks; let ks = keystore_header;
ks.certs.push(KSCert { ks.certs.push(KSCert {
id: ks.current_cert + 1, id: ks.current_cert + 1,