keystore v2 work
This commit is contained in:
parent
bafc361e76
commit
e901f63bb9
|
@ -17,10 +17,11 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
|||
use sea_orm::{ActiveModelTrait, EntityTrait};
|
||||
use trifid_pki::cert::{deserialize_ed25519_public, deserialize_x25519_public};
|
||||
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 sea_orm::{ColumnTrait, QueryFilter, IntoActiveModel};
|
||||
use sea_orm::ActiveValue::Set;
|
||||
use trifid_api_entities::entity::prelude::KeystoreHost;
|
||||
|
||||
#[post("/v1/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 host_in_ks {
|
||||
let host_in_ks = match keystore_host::Entity::find().filter(keystore_host::Column::Id.eq(host)).one(&db.conn).await {
|
||||
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,
|
||||
None => {
|
||||
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."
|
||||
.to_string(),
|
||||
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
|
||||
.client_keys
|
||||
.iter()
|
||||
.find(|u| u.id == req.counter as u64);
|
||||
let client_keys_2 = host_in_ks
|
||||
.client_keys
|
||||
.iter()
|
||||
.find(|u| u.id == host_in_ks.current_client_key);
|
||||
let keystore_data = match key_info {
|
||||
Some(key_info) => key_info,
|
||||
None => {
|
||||
return HttpResponse::Unauthorized().json(vec![APIError {
|
||||
code: "ERR_HOST_ERROR".to_string(),
|
||||
message: "The host does not exist or you do not have permission to access it."
|
||||
.to_string(),
|
||||
path: None,
|
||||
}]);
|
||||
}
|
||||
};
|
||||
|
||||
let signature = match Signature::from_slice(&req.signature) {
|
||||
Ok(sig) => sig,
|
||||
|
@ -90,27 +119,9 @@ pub async fn dnclient(
|
|||
}
|
||||
};
|
||||
|
||||
let mut valid = false;
|
||||
let mut valid_key = None;
|
||||
let key = VerifyingKey::from(keystore_data.client_signing_key.try_into().unwrap());
|
||||
|
||||
if let Some(client_keys) = client_keys {
|
||||
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 {
|
||||
if !key.verify(&req.message.as_bytes(), &signature).is_ok() {
|
||||
// Be intentionally vague as the message is invalid.
|
||||
warn!("! invalid signature from {}", host);
|
||||
return HttpResponse::Unauthorized().json(vec![APIError {
|
||||
|
@ -121,8 +132,6 @@ pub async fn dnclient(
|
|||
}]);
|
||||
}
|
||||
|
||||
let client_keys = valid_key.unwrap();
|
||||
|
||||
// Sig OK
|
||||
// Decode the message from base64
|
||||
|
||||
|
@ -190,7 +199,7 @@ pub async fn dnclient(
|
|||
|
||||
// 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,
|
||||
Err(e) => {
|
||||
return HttpResponse::InternalServerError().json(EnrollResponse::Error {
|
||||
|
@ -218,13 +227,10 @@ pub async fn dnclient(
|
|||
}
|
||||
};
|
||||
|
||||
let current_cfg = host_in_ks
|
||||
.config
|
||||
.iter()
|
||||
.find(|u| u.id == host_in_ks.current_config);
|
||||
let current_cfg = keystore_data.config;
|
||||
let generated_config_string = serde_yaml::to_string(&cfg).unwrap();
|
||||
|
||||
let config_update_avail = current_cfg.map(|u| u.config.clone()) != Some(cfg.clone())
|
||||
|| req.counter < host_in_ks.current_config as u32;
|
||||
let config_update_avail = current_cfg != generated_config_string || req.counter < keystore_header.counter as u32;
|
||||
|
||||
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);
|
||||
|
@ -315,7 +321,7 @@ pub async fn dnclient(
|
|||
}
|
||||
};
|
||||
|
||||
let ks = host_in_ks;
|
||||
let ks = keystore_header;
|
||||
|
||||
ks.certs.push(KSCert {
|
||||
id: ks.current_cert + 1,
|
||||
|
|
Loading…
Reference in New Issue