prevents packages from producing conflicting ssl configs (#1195)

* prevents packages from producing conflicting ssl configs

* remove commented code

commits missing file

fix builds
This commit is contained in:
Keagan McClelland
2022-02-11 15:36:35 -07:00
parent 384bd74dee
commit b4269ce09b
5 changed files with 103 additions and 3 deletions

View File

@@ -1,4 +1,5 @@
pub mod model;
pub mod package;
pub mod util;
use std::borrow::Cow;

View File

@@ -223,6 +223,15 @@ impl PackageDataEntry {
Self::Updating { installed, .. } | Self::Installed { installed, .. } => Some(installed),
}
}
pub fn manifest(self) -> Manifest {
match self {
PackageDataEntry::Installing { manifest, .. } => manifest,
PackageDataEntry::Updating { manifest, .. } => manifest,
PackageDataEntry::Restoring { manifest, .. } => manifest,
PackageDataEntry::Removing { manifest, .. } => manifest,
PackageDataEntry::Installed { manifest, .. } => manifest,
}
}
}
impl PackageDataEntryModel {
pub fn installed(self) -> OptionModel<InstalledPackageDataEntry> {

25
backend/src/db/package.rs Normal file
View File

@@ -0,0 +1,25 @@
use patch_db::DbHandle;
use crate::s9pk::manifest::{Manifest, PackageId};
use crate::Error;
pub async fn get_packages<Db: DbHandle>(db: &mut Db) -> Result<Vec<PackageId>, Error> {
let packages = crate::db::DatabaseModel::new()
.package_data()
.get(db, false)
.await?;
Ok(packages.0.keys().cloned().collect())
}
pub async fn get_manifest<Db: DbHandle>(
db: &mut Db,
pkg: &PackageId,
) -> Result<Option<Manifest>, Error> {
let mpde = crate::db::DatabaseModel::new()
.package_data()
.idx_model(pkg)
.get(db, false)
.await?
.into_owned();
Ok(mpde.map(|pde| pde.manifest()))
}

View File

@@ -63,6 +63,7 @@ pub enum ErrorKind {
Incoherent = 55,
InvalidBackupTargetId = 56,
ProductKeyMismatch = 57,
LanPortConflict = 58,
}
impl ErrorKind {
pub fn as_str(&self) -> &'static str {
@@ -125,6 +126,7 @@ impl ErrorKind {
Incoherent => "Incoherent",
InvalidBackupTargetId => "Invalid Backup Target ID",
ProductKeyMismatch => "Incompatible Product Keys",
LanPortConflict => "Incompatible LAN port configuration",
}
}
}

View File

@@ -9,8 +9,8 @@ use std::time::{Duration, Instant};
use color_eyre::eyre::eyre;
use emver::VersionRange;
use futures::future::BoxFuture;
use futures::{FutureExt, StreamExt, TryStreamExt};
use futures::future::{self, BoxFuture};
use futures::{stream, FutureExt, StreamExt, TryStreamExt};
use http::header::CONTENT_LENGTH;
use http::{Request, Response, StatusCode};
use hyper::Body;
@@ -43,7 +43,7 @@ use crate::s9pk::manifest::{Manifest, PackageId};
use crate::s9pk::reader::S9pkReader;
use crate::status::{MainStatus, Status};
use crate::util::io::{copy_and_shutdown, response_to_reader};
use crate::util::serde::{display_serializable, IoFormat};
use crate::util::serde::{display_serializable, IoFormat, Port};
use crate::util::{display_none, AsyncFileExt, Version};
use crate::version::{Current, VersionT};
use crate::volume::asset_dir;
@@ -124,6 +124,7 @@ pub async fn install(
.json()
.await
.with_kind(crate::ErrorKind::Registry)?;
let s9pk = s9pk
.error_for_status()
.with_kind(crate::ErrorKind::Registry)?;
@@ -651,6 +652,51 @@ pub async fn download_install_s9pk(
let version = &temp_manifest.version;
if let Err(e) = async {
let mut db_handle = ctx.db.handle();
let mut tx = db_handle.begin().await?;
// Build set of existing manifests
let mut manifests = Vec::new();
for pkg in crate::db::package::get_packages(&mut tx).await? {
match crate::db::package::get_manifest(&mut tx, &pkg).await? {
Some(m) => {
manifests.push(m);
}
None => {}
}
}
// Build map of current port -> ssl mappings
let port_map = ssl_port_status(&manifests);
tracing::info!("SSL Port Map: {:?}", &port_map);
// if any of the requested interface lan configs conflict with current state, fail the install
for (_id, iface) in &temp_manifest.interfaces.0 {
if let Some(cfg) = &iface.lan_config {
for (p, lan) in cfg {
if p.0 == 80 && lan.ssl || p.0 == 443 && !lan.ssl {
return Err(Error::new(
eyre!("SSL Conflict with EmbassyOS"),
ErrorKind::LanPortConflict,
));
}
match port_map.get(&p) {
Some((ssl, pkg)) => {
if *ssl != lan.ssl {
return Err(Error::new(
eyre!("SSL Conflict with package: {}", pkg),
ErrorKind::LanPortConflict,
));
}
}
None => {
continue;
}
}
}
}
}
tx.save().await?;
drop(db_handle);
let pkg_archive_dir = ctx
.datadir
.join(PKG_ARCHIVE_DIR)
@@ -1345,3 +1391,20 @@ pub fn load_images<'a, P: AsRef<Path> + 'a + Send + Sync>(
}
.boxed()
}
fn ssl_port_status(manifests: &Vec<Manifest>) -> BTreeMap<Port, (bool, PackageId)> {
let mut ret = BTreeMap::new();
for m in manifests {
for (_id, iface) in &m.interfaces.0 {
match &iface.lan_config {
None => {}
Some(cfg) => {
for (p, lan) in cfg {
ret.insert(p.clone(), (lan.ssl, m.id.clone()));
}
}
}
}
}
ret
}