Skip to content

Commit 016cf4e

Browse files
committed
GitHub asset digest verification
1 parent eca869d commit 016cf4e

9 files changed

Lines changed: 151 additions & 33 deletions

File tree

src/apt/deb.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use sha2::{Sha256, Sha512};
1212

1313
use crate::{
1414
package::{Data, Package},
15-
utils::{Arch, hashsum},
15+
utils::{Arch, Digest, ReleaseChannel, hashsum},
1616
};
1717

1818
static ARCH: LazyLock<Regex> = LazyLock::new(|| Regex::new(r#"Architecture: (\w+)"#).unwrap());
@@ -33,7 +33,7 @@ impl DebianPackage {
3333
/// Create a new Debian package from a package.
3434
///
3535
/// Also sets metadata of the package.
36-
pub fn from_package(package: &Package) -> Result<Self> {
36+
pub fn from_package(package: &Package, channel: &ReleaseChannel) -> Result<Self> {
3737
// Create the debian package from the metadata if it is present.
3838
if let Data::Metadata(metadata) = package.data() {
3939
let package: DebianPackage = from_str(&metadata)?;
@@ -49,12 +49,22 @@ impl DebianPackage {
4949
.context("Error occurred while parsing the debian control file from package")?
5050
.trim_end()
5151
.to_owned();
52-
let filename = format!("pool/stable/{}/{}", package.version(), package.file_name());
52+
let filename = format!(
53+
"pool/{channel}/{}/{}",
54+
package.version(),
55+
package.file_name()
56+
);
5357

5458
let size = data.len();
5559
let md5 = hashsum::<Md5>(&data);
5660
let sha1 = hashsum::<Sha1>(&data);
57-
let sha256 = hashsum::<Sha256>(&data);
61+
62+
let sha256 = if let Some(Digest::Sha256(digest)) = package.digest() {
63+
digest.clone()
64+
} else {
65+
hashsum::<Sha256>(&data)
66+
};
67+
5868
let sha512 = hashsum::<Sha512>(&data);
5969

6070
let deb = Self {
@@ -135,7 +145,7 @@ mod tests {
135145
let data = read("data/OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb").unwrap();
136146
package.set_package_data(data);
137147

138-
let deb = DebianPackage::from_package(&package).unwrap();
148+
let deb = DebianPackage::from_package(&package, &ReleaseChannel::Stable).unwrap();
139149
assert_eq!(deb.get_arch(), Some(Arch::Amd64));
140150
}
141151

@@ -144,7 +154,7 @@ mod tests {
144154
fn test_without_data() {
145155
let package = package("OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb");
146156

147-
let _ = DebianPackage::from_package(&package).unwrap();
157+
let _ = DebianPackage::from_package(&package, &ReleaseChannel::Stable).unwrap();
148158
}
149159

150160
#[test]
@@ -153,11 +163,11 @@ mod tests {
153163
let data = read("data/OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb").unwrap();
154164
package.set_package_data(data);
155165

156-
let _ = DebianPackage::from_package(&package).unwrap();
166+
let _ = DebianPackage::from_package(&package, &ReleaseChannel::Stable).unwrap();
157167

158168
// The package data should have been replaced by the metadata
159169
assert!(matches!(package.data(), Data::Metadata(_)));
160170

161-
let _ = DebianPackage::from_package(&package).unwrap();
171+
let _ = DebianPackage::from_package(&package, &ReleaseChannel::Stable).unwrap();
162172
}
163173
}

src/apt/index.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ struct Files {
4545
}
4646

4747
impl AptIndices {
48-
pub fn new(packages: &[Package]) -> Result<AptIndices> {
48+
pub fn new(packages: &[Package], channel: &ReleaseChannel) -> Result<AptIndices> {
4949
let mut debian: BTreeMap<Arch, Vec<DebianPackage>> = BTreeMap::new();
5050
// Find the latest date from the list of packages
5151
let mut date = DateTime::UNIX_EPOCH;
@@ -54,7 +54,7 @@ impl AptIndices {
5454
date = *package.creation_date();
5555
}
5656

57-
match DebianPackage::from_package(package) {
57+
match DebianPackage::from_package(package, channel) {
5858
Ok(deb) => {
5959
if let Some(arch) = deb.get_arch() {
6060
debian.entry(arch).or_default().push(deb);
@@ -152,13 +152,13 @@ mod tests {
152152

153153
#[test]
154154
fn test_apt_indices() {
155-
let package = Package::detect_package("OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb", "2.0.0".to_owned(), "https://github.com/OpenBangla/OpenBangla-Keyboard/releases/download/2.0.0/OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb".to_owned(), DateTime::parse_from_rfc2822("Wed, 8 Nov 2023 16:40:12 +0000").unwrap().into()).unwrap();
155+
let package = Package::detect_package("OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb", "2.0.0".to_owned(), "https://github.com/OpenBangla/OpenBangla-Keyboard/releases/download/2.0.0/OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb".to_owned(), None, DateTime::parse_from_rfc2822("Wed, 8 Nov 2023 16:40:12 +0000").unwrap().into()).unwrap();
156156
let data = read("data/OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb").unwrap();
157157
package.set_package_data(data);
158158

159159
let packages = vec![package];
160160

161-
let indices = AptIndices::new(&packages).unwrap();
161+
let indices = AptIndices::new(&packages, &ReleaseChannel::Stable).unwrap();
162162

163163
// Packages
164164
let packages = indices.get_package_index(&Arch::Amd64);
@@ -181,7 +181,7 @@ mod tests {
181181

182182
let packages = vec![package1, package2];
183183

184-
let indices = AptIndices::new(&packages).unwrap();
184+
let indices = AptIndices::new(&packages, &ReleaseChannel::Stable).unwrap();
185185

186186
// Packages
187187
let packages = indices.get_package_index(&Arch::Amd64);
@@ -229,7 +229,7 @@ mod tests {
229229
package1, package2, package3, package4, package5, package6, package7,
230230
];
231231

232-
let indices = AptIndices::new(&packages).unwrap();
232+
let indices = AptIndices::new(&packages, &ReleaseChannel::Stable).unwrap();
233233

234234
// Release
235235
let release = indices.get_release_index(&ReleaseChannel::Stable);

src/apt/routes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ async fn release_index(
3232
let mut repo = Repository::from_github(&owner, &repo, &channel, &state).await;
3333
let packages = repo.select_package_apt(&distro, agent.as_str()).await?;
3434

35-
let index = AptIndices::new(&packages)?;
35+
let index = AptIndices::new(&packages, &channel)?;
3636
repo.save_package_metadata().await;
3737

3838
let release_file = index.get_release_index(&channel);
@@ -67,7 +67,7 @@ async fn packages_file(
6767
let mut repo = Repository::from_github(&owner, &repo, &channel, &state).await;
6868
let packages = repo.select_package_apt(&distro, agent.as_str()).await?;
6969

70-
let index = AptIndices::new(&packages)?;
70+
let index = AptIndices::new(&packages, &channel)?;
7171
repo.save_package_metadata().await;
7272

7373
let Ok(arch) = arch.parse::<Arch>() else {

src/db.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ mod tests {
5454
testcontainers::{ContainerAsync, runners::AsyncRunner},
5555
};
5656

57-
use crate::apt::DebianPackage;
57+
use crate::{apt::DebianPackage, utils::ReleaseChannel};
5858

5959
pub async fn setup_mongodb(container: &ContainerAsync<Mongo>) -> Client {
6060
let host = container.get_host().await.unwrap();
@@ -70,11 +70,11 @@ mod tests {
7070
let container = Mongo::default().start().await.unwrap();
7171
let client = setup_mongodb(&container).await;
7272

73-
let package = Package::detect_package("OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb", "2.0.0".to_owned(), "https://github.com/OpenBangla/OpenBangla-Keyboard/releases/download/2.0.0/OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb".to_owned(), DateTime::parse_from_rfc3339("2024-07-01T00:00:00Z").unwrap().into()).unwrap();
73+
let package = Package::detect_package("OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb", "2.0.0".to_owned(), "https://github.com/OpenBangla/OpenBangla-Keyboard/releases/download/2.0.0/OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb".to_owned(), None, DateTime::parse_from_rfc3339("2024-07-01T00:00:00Z").unwrap().into()).unwrap();
7474
let data = read("data/OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb").unwrap();
7575
package.set_package_data(data);
7676

77-
let _ = DebianPackage::from_package(&package).unwrap();
77+
let _ = DebianPackage::from_package(&package, &ReleaseChannel::Stable).unwrap();
7878

7979
let db = client.database("github");
8080
let collection = db.collection::<PackageMetadata>("test");
@@ -89,7 +89,7 @@ mod tests {
8989

9090
assert_eq!(metadata, retrieved);
9191

92-
let non_existent = Package::detect_package("OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb", "2.0.0".to_owned(), "https://github.com/OpenBangla/OpenBangla-Keyboard/releases/download/2.0.0/OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb".to_owned(), DateTime::parse_from_rfc3339("2024-07-10T00:00:00Z").unwrap().into()).unwrap();
92+
let non_existent = Package::detect_package("OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb", "2.0.0".to_owned(), "https://github.com/OpenBangla/OpenBangla-Keyboard/releases/download/2.0.0/OpenBangla-Keyboard_2.0.0-ubuntu20.04.deb".to_owned(), None, DateTime::parse_from_rfc3339("2024-07-10T00:00:00Z").unwrap().into()).unwrap();
9393

9494
assert_eq!(
9595
PackageMetadata::retrieve_from(&collection, &non_existent).await,

src/package.rs

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ use std::sync::{Arc, Mutex};
22

33
use anyhow::{Result, bail};
44
use chrono::{DateTime, Utc};
5+
use tracing::info;
56

67
use crate::{
78
REQWEST,
89
detect::PackageInfo,
9-
utils::{Arch, Dist, Type},
10+
utils::{Arch, Digest, Dist, Type},
1011
};
1112

1213
struct InnerPackage {
@@ -15,6 +16,7 @@ struct InnerPackage {
1516
url: String,
1617
ver: String,
1718
data: Mutex<Data>,
19+
digest: Option<Digest>,
1820
created: DateTime<Utc>,
1921
}
2022

@@ -76,6 +78,7 @@ impl Package {
7678
name: &str,
7779
ver: String,
7880
url: String,
81+
digest: Option<Digest>,
7982
created: DateTime<Utc>,
8083
) -> Result<Package> {
8184
// Split the extension first.
@@ -91,6 +94,7 @@ impl Package {
9194
info,
9295
url,
9396
ver,
97+
digest,
9498
data: Mutex::new(Data::None),
9599
created,
96100
};
@@ -116,6 +120,7 @@ impl Package {
116120
.unwrap_or_default()
117121
}
118122

123+
/// Type of the package
119124
pub fn ty(&self) -> &Type {
120125
&self.inner.tipe
121126
}
@@ -130,6 +135,11 @@ impl Package {
130135
&self.inner.ver
131136
}
132137

138+
/// Return the digest of the package if available.
139+
pub fn digest(&self) -> Option<&Digest> {
140+
self.inner.digest.as_ref()
141+
}
142+
133143
pub fn download_url(&self) -> &str {
134144
&self.inner.url
135145
}
@@ -152,6 +162,22 @@ impl Package {
152162
Ok(())
153163
}
154164

165+
pub fn verify_digest(&self) -> Result<bool> {
166+
let data = &*self.inner.data.lock().unwrap();
167+
168+
let data = match data {
169+
Data::Package(d) => d,
170+
_ => bail!("No package data available"),
171+
};
172+
173+
if let Some(digest) = &self.inner.digest {
174+
info!("Verifying package digest for {}", self.file_name());
175+
Ok(digest.verify(data))
176+
} else {
177+
bail!("No digest available for verification");
178+
}
179+
}
180+
155181
/// Return the data of the package.
156182
///
157183
/// It is required to call the `download()` or `set_metadata()` function before calling this.
@@ -218,16 +244,28 @@ pub(crate) mod tests {
218244
///
219245
/// For testing purpose.
220246
pub(crate) fn package(p: &str) -> Package {
221-
Package::detect_package(p, String::new(), p.to_owned(), chrono::DateTime::UNIX_EPOCH)
222-
.unwrap()
247+
Package::detect_package(
248+
p,
249+
String::new(),
250+
p.to_owned(),
251+
None,
252+
chrono::DateTime::UNIX_EPOCH,
253+
)
254+
.unwrap()
223255
}
224256

225257
/// A shorthand for `Package::detect_package()`
226258
///
227259
/// For testing purpose.
228260
pub(crate) fn package_with_ver(p: &str, v: &str) -> Package {
229-
Package::detect_package(p, v.to_owned(), p.to_owned(), chrono::DateTime::UNIX_EPOCH)
230-
.unwrap()
261+
Package::detect_package(
262+
p,
263+
v.to_owned(),
264+
p.to_owned(),
265+
None,
266+
chrono::DateTime::UNIX_EPOCH,
267+
)
268+
.unwrap()
231269
}
232270

233271
#[test]
@@ -236,6 +274,7 @@ pub(crate) mod tests {
236274
"OpenBangla-Keyboard_2.0.0-ubuntu22.04.deb",
237275
"2.0.0".to_owned(),
238276
String::new(),
277+
None,
239278
DateTime::UNIX_EPOCH,
240279
)
241280
.unwrap();
@@ -247,6 +286,7 @@ pub(crate) mod tests {
247286
"OpenBangla-Keyboard_2.0.0-fedora36.rpm",
248287
"2.0.0".to_owned(),
249288
String::new(),
289+
None,
250290
DateTime::UNIX_EPOCH,
251291
)
252292
.unwrap();
@@ -258,6 +298,7 @@ pub(crate) mod tests {
258298
"caprine_2.56.1_amd64.deb",
259299
"v2.56.1".to_owned(),
260300
String::new(),
301+
None,
261302
DateTime::UNIX_EPOCH,
262303
)
263304
.unwrap();
@@ -269,6 +310,7 @@ pub(crate) mod tests {
269310
"ibus-openbangla_3.0.0-opensuse-tumbleweed.rpm",
270311
"3.0.0".to_owned(),
271312
String::new(),
313+
None,
272314
DateTime::UNIX_EPOCH,
273315
)
274316
.unwrap();
@@ -283,6 +325,7 @@ pub(crate) mod tests {
283325
"OpenBangla-Keyboard_2.0.0-ubuntu22.04.deb",
284326
"2.0.0".to_owned(),
285327
String::new(),
328+
None,
286329
DateTime::UNIX_EPOCH,
287330
)
288331
.unwrap();

0 commit comments

Comments
 (0)