Backport some upstream bug fixes
- Set supplementary groups when dropping privileges - Show more descriptive error messages on missing files errors - Create /usr/libexec/keylime directory Related: rhbz#2084552 Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
This commit is contained in:
parent
9ab97f2b94
commit
c7b2752739
@ -47,8 +47,18 @@ Source0: %{url}/archive/%{commit}/rust-keylime-%{version}.tar.gz
|
||||
# cargo vendor
|
||||
# tar jcf rust-keylime-%%{version}-vendor.tar.xz vendor
|
||||
Source1: rust-keylime-%{version}-vendor.tar.xz
|
||||
Patch0: rust-keylime-fix-metadata.diff
|
||||
# Drop dependencies and adjust the features
|
||||
Patch0: rust-keylime-drop-dependencies.patch
|
||||
# Add serialization functions to fix issue on big-endian arches
|
||||
Patch1: rust-keylime-add-quote-serialization.patch
|
||||
# Show path on missing mTLS certificate
|
||||
Patch2: rust-keylime-show-path-missing-cert.patch
|
||||
# Use more descriptive error messages for missing files errors
|
||||
Patch3: rust-keylime-descriptive-error-messages.patch
|
||||
# Set supplementary groups when dropping privileges
|
||||
Patch4: rust-keylime-set-supplementary-groups.patch
|
||||
# Adjust the supported and required features
|
||||
Patch5: rust-keylime-adjust-features.patch
|
||||
|
||||
ExclusiveArch: %{rust_arches}
|
||||
|
||||
@ -105,8 +115,9 @@ Provides: bundled(crate(cexpr)) = 0.6.0
|
||||
Provides: bundled(crate(cfg-if)) = 1.0.0
|
||||
Provides: bundled(crate(clang-sys)) = 1.3.3
|
||||
Provides: bundled(crate(clap)) = 2.34.0
|
||||
Provides: bundled(crate(clap)) = 3.0.14
|
||||
Provides: bundled(crate(clap_derive)) = 3.0.14
|
||||
Provides: bundled(crate(clap)) = 3.1.18
|
||||
Provides: bundled(crate(clap_derive)) = 3.1.18
|
||||
Provides: bundled(crate(clap_lex)) = 0.2.4
|
||||
Provides: bundled(crate(compress-tools)) = 0.12.2
|
||||
Provides: bundled(crate(convert_case)) = 0.4.0
|
||||
Provides: bundled(crate(cookie)) = 0.16.0
|
||||
@ -118,7 +129,7 @@ Provides: bundled(crate(crypto-common)) = 0.1.3
|
||||
Provides: bundled(crate(derive_more)) = 0.99.17
|
||||
Provides: bundled(crate(digest)) = 0.10.3
|
||||
Provides: bundled(crate(dlv-list)) = 0.2.3
|
||||
Provides: bundled(crate(either)) = 1.6.1
|
||||
Provides: bundled(crate(either)) = 1.7.0
|
||||
Provides: bundled(crate(encoding_rs)) = 0.8.30
|
||||
Provides: bundled(crate(enumflags2)) = 0.7.3
|
||||
Provides: bundled(crate(enumflags2_derive)) = 0.7.3
|
||||
@ -170,7 +181,7 @@ Provides: bundled(crate(keylime_agent)) = 0.1.0
|
||||
Provides: bundled(crate(language-tags)) = 0.3.2
|
||||
Provides: bundled(crate(lazy_static)) = 1.4.0
|
||||
Provides: bundled(crate(lazycell)) = 1.3.0
|
||||
Provides: bundled(crate(libc)) = 0.2.118
|
||||
Provides: bundled(crate(libc)) = 0.2.126
|
||||
Provides: bundled(crate(libloading)) = 0.7.3
|
||||
Provides: bundled(crate(local-channel)) = 0.1.2
|
||||
Provides: bundled(crate(local-waker)) = 0.1.2
|
||||
@ -230,7 +241,6 @@ Provides: bundled(crate(remove_dir_all)) = 0.5.3
|
||||
Provides: bundled(crate(reqwest)) = 0.11.10
|
||||
Provides: bundled(crate(rust-ini)) = 0.17.0
|
||||
Provides: bundled(crate(rustc-hash)) = 1.1.0
|
||||
Provides: bundled(crate(rustc-serialize)) = 0.3.24
|
||||
Provides: bundled(crate(rustc_version)) = 0.3.3
|
||||
Provides: bundled(crate(rustc_version)) = 0.4.0
|
||||
Provides: bundled(crate(ryu)) = 1.0.9
|
||||
@ -261,7 +271,7 @@ Provides: bundled(crate(target-lexicon)) = 0.12.3
|
||||
Provides: bundled(crate(tempfile)) = 3.3.0
|
||||
Provides: bundled(crate(termcolor)) = 1.1.2
|
||||
Provides: bundled(crate(textwrap)) = 0.11.0
|
||||
Provides: bundled(crate(textwrap)) = 0.14.2
|
||||
Provides: bundled(crate(textwrap)) = 0.15.0
|
||||
Provides: bundled(crate(thiserror)) = 1.0.30
|
||||
Provides: bundled(crate(thiserror-impl)) = 1.0.30
|
||||
Provides: bundled(crate(time)) = 0.3.9
|
||||
@ -302,7 +312,7 @@ Provides: bundled(crate(wasm-bindgen-macro)) = 0.2.79
|
||||
Provides: bundled(crate(wasm-bindgen-macro-support)) = 0.2.79
|
||||
Provides: bundled(crate(wasm-bindgen-shared)) = 0.2.79
|
||||
Provides: bundled(crate(web-sys)) = 0.3.56
|
||||
Provides: bundled(crate(which)) = 4.2.4
|
||||
Provides: bundled(crate(which)) = 4.2.5
|
||||
Provides: bundled(crate(winapi)) = 0.3.9
|
||||
Provides: bundled(crate(winapi-i686-pc-windows-gnu)) = 0.4.0
|
||||
Provides: bundled(crate(winapi-util)) = 0.1.5
|
||||
@ -327,7 +337,7 @@ Rust agent for Keylime
|
||||
find -name '*.rs' -type f -perm /111 -exec chmod -v -x '{}' '+'
|
||||
|
||||
%build
|
||||
%cargo_build
|
||||
%cargo_build --no-default-features
|
||||
|
||||
%install
|
||||
%cargo_install
|
||||
@ -358,6 +368,7 @@ install -Dpm 644 ./dist/systemd/system/var-lib-keylime-secure.mount \
|
||||
%attr(700,keylime,keylime) %dir %{_rundir}/keylime
|
||||
%attr(700,keylime,keylime) %dir %{_localstatedir}/log/keylime
|
||||
%attr(700,keylime,keylime) %{_sharedstatedir}/keylime
|
||||
%attr(700,keylime,keylime) %{_libexecdir}/keylime
|
||||
%{_bindir}/keylime_agent
|
||||
%{_bindir}/keylime_ima_emulator
|
||||
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
diff --git a/Cargo.toml b/Cargo.toml
|
||||
index 95bbfab..200fbc7 100644
|
||||
--- a/Cargo.toml
|
||||
+++ b/Cargo.toml
|
||||
@@ -39,25 +39,16 @@ serde_json = { version = "1.0", features = ["raw_value"] }
|
||||
--- a/Cargo.toml 2022-07-01 10:59:27.103854970 +0200
|
||||
+++ b/Cargo.toml 2022-07-01 11:02:07.772529002 +0200
|
||||
@@ -37,25 +37,15 @@
|
||||
static_assertions = "1"
|
||||
tempfile = "3.0.4"
|
||||
tokio = {version = "1", features = ["full"]}
|
||||
@ -17,7 +15,7 @@ index 95bbfab..200fbc7 100644
|
||||
-wiremock = "0.5"
|
||||
|
||||
[features]
|
||||
# The features enabled by default
|
||||
-# The features enabled by default
|
||||
-default = ["with-zmq", "legacy-python-actions"]
|
||||
+# Removed default features to drop ZeroMQ and the need for the python shim
|
||||
+default = []
|
||||
43
rust-keylime-descriptive-error-messages.patch
Normal file
43
rust-keylime-descriptive-error-messages.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From e20b936fc9d92ae05406cb86471d3e6fba823b7f Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Tue, 28 Jun 2022 13:47:38 +0200
|
||||
Subject: [PATCH] main: Use more descriptive message for missing files error
|
||||
|
||||
Use more descriptive message when required paths are missing instead of
|
||||
the generic message.
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
---
|
||||
src/main.rs | 19 ++++++++++++++++---
|
||||
1 file changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/main.rs b/src/main.rs
|
||||
index 9404284..ef29eb2 100644
|
||||
--- a/src/main.rs
|
||||
+++ b/src/main.rs
|
||||
@@ -608,9 +608,22 @@ async fn main() -> Result<()> {
|
||||
let payload = Arc::clone(&encr_payload_arc);
|
||||
|
||||
let revocation_cert = revocation::get_revocation_cert_path(&config)?;
|
||||
- let actions_dir =
|
||||
- Path::new(&config.revocation_actions_dir).canonicalize()?;
|
||||
- let work_dir = Path::new(&config.work_dir).canonicalize()?;
|
||||
+ let actions_dir = Path::new(&config.revocation_actions_dir)
|
||||
+ .canonicalize()
|
||||
+ .map_err(|e| {
|
||||
+ Error::Configuration(format!(
|
||||
+ "Path {} set in revocation_actions_dir not found: {}",
|
||||
+ &config.revocation_actions_dir, e
|
||||
+ ))
|
||||
+ })?;
|
||||
+
|
||||
+ let work_dir =
|
||||
+ Path::new(&config.work_dir).canonicalize().map_err(|e| {
|
||||
+ Error::Configuration(format!(
|
||||
+ "Path {} set in keylime_dir not found: {}",
|
||||
+ &config.work_dir, e
|
||||
+ ))
|
||||
+ })?;
|
||||
|
||||
let quotedata = web::Data::new(QuoteData {
|
||||
tpmcontext: Mutex::new(ctx),
|
||||
94
rust-keylime-drop-dependencies.patch
Normal file
94
rust-keylime-drop-dependencies.patch
Normal file
@ -0,0 +1,94 @@
|
||||
diff --git a/Cargo.toml b/Cargo.toml
|
||||
index 92f3974..f0c7d39 100644
|
||||
--- a/Cargo.toml
|
||||
+++ b/Cargo.toml
|
||||
@@ -21,7 +21,7 @@ doc = false
|
||||
actix-web = { version = "4", features = ["openssl"] }
|
||||
base64 = "0.13"
|
||||
cfg-if = "1"
|
||||
-clap = { version = "3.0.14", features = ["derive"] }
|
||||
+clap = { version = "~3.1.18", features = ["derive"] }
|
||||
compress-tools = "0.12"
|
||||
flate2 = "1.0.4"
|
||||
futures = "0.3.6"
|
||||
diff --git a/src/main.rs b/src/main.rs
|
||||
index 1896104..8540597 100644
|
||||
--- a/src/main.rs
|
||||
+++ b/src/main.rs
|
||||
@@ -51,7 +51,7 @@ mod tpm;
|
||||
mod version_handler;
|
||||
|
||||
use actix_web::{dev::Service, http, middleware, rt, web, App, HttpServer};
|
||||
-use clap::{App as ClapApp, Arg};
|
||||
+use clap::{Arg, Command as ClapApp};
|
||||
use common::*;
|
||||
use compress_tools::*;
|
||||
use error::{Error, Result};
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
||||
diff --git a/Cargo.toml b/Cargo.toml
|
||||
index f0c7d39..0f4e4ab 100644
|
||||
--- a/Cargo.toml
|
||||
+++ b/Cargo.toml
|
||||
@@ -34,7 +34,6 @@ picky-asn1-x509 = "0.6.1"
|
||||
pretty_env_logger = "0.4"
|
||||
reqwest = {version = "0.11", features = ["json"]}
|
||||
rust-ini = "0.17"
|
||||
-rustc-serialize = "0.3.24"
|
||||
serde = "1.0.80"
|
||||
serde_derive = "1.0.80"
|
||||
serde_json = { version = "1.0", features = ["raw_value"] }
|
||||
--
|
||||
2.35.3
|
||||
|
||||
|
||||
From f7b59a6a7739d275ffe15a915eb48a36ceafccdd Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Tue, 17 May 2022 18:56:50 +0200
|
||||
Subject: [PATCH 3/3] Drop unused dependency flate2
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
---
|
||||
Cargo.lock | 1 -
|
||||
Cargo.toml | 1 -
|
||||
src/tpm.rs | 3 ---
|
||||
3 files changed, 5 deletions(-)
|
||||
|
||||
diff --git a/Cargo.toml b/Cargo.toml
|
||||
index 0f4e4ab..69d2eec 100644
|
||||
--- a/Cargo.toml
|
||||
+++ b/Cargo.toml
|
||||
@@ -23,7 +23,6 @@ base64 = "0.13"
|
||||
cfg-if = "1"
|
||||
clap = { version = "~3.1.18", features = ["derive"] }
|
||||
compress-tools = "0.12"
|
||||
-flate2 = "1.0.4"
|
||||
futures = "0.3.6"
|
||||
hex = "0.4"
|
||||
libc = "0.2.43"
|
||||
diff --git a/src/tpm.rs b/src/tpm.rs
|
||||
index 355dd0d..43129f1 100644
|
||||
--- a/src/tpm.rs
|
||||
+++ b/src/tpm.rs
|
||||
@@ -20,8 +20,6 @@ use openssl::{
|
||||
pkey::{Id, PKeyRef, Public},
|
||||
};
|
||||
|
||||
-use flate2::{write::ZlibEncoder, Compression};
|
||||
-
|
||||
use tss_esapi::{
|
||||
abstraction::{
|
||||
ak,
|
||||
@@ -635,7 +633,6 @@ pub(crate) fn quote(
|
||||
#[cfg(test)]
|
||||
pub mod testing {
|
||||
use super::*;
|
||||
- use flate2::read::ZlibDecoder;
|
||||
use tss_esapi::constants::structure_tags::StructureTag;
|
||||
use tss_esapi::structures::{Attest, AttestBuffer, DigestList, Ticket};
|
||||
use tss_esapi::tss2_esys::Tss2_MU_TPMT_SIGNATURE_Unmarshal;
|
||||
--
|
||||
2.35.3
|
||||
|
||||
162
rust-keylime-set-supplementary-groups.patch
Normal file
162
rust-keylime-set-supplementary-groups.patch
Normal file
@ -0,0 +1,162 @@
|
||||
From 4ec807b1bbcfaa67f85d0c2659b1f439c2f540b4 Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Fri, 24 Jun 2022 16:25:54 +0200
|
||||
Subject: [PATCH] permissions: Set supplementary groups when dropping
|
||||
privileges
|
||||
|
||||
This allows the agent to run with the user primary group and have the
|
||||
access given by the supplementary groups.
|
||||
|
||||
Fixes: #414
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
---
|
||||
src/permissions.rs | 70 ++++++++++++++++++++++++++++++++++------------
|
||||
1 file changed, 52 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/src/permissions.rs b/src/permissions.rs
|
||||
index 279a6dd..86e3fae 100644
|
||||
--- a/src/permissions.rs
|
||||
+++ b/src/permissions.rs
|
||||
@@ -2,7 +2,7 @@
|
||||
// Copyright 2021 Keylime Authors
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
-use libc::{gid_t, uid_t};
|
||||
+use libc::{c_char, c_int, gid_t, uid_t};
|
||||
use log::*;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::{
|
||||
@@ -13,10 +13,9 @@ use std::{
|
||||
ptr,
|
||||
};
|
||||
|
||||
-#[derive(Debug)]
|
||||
pub(crate) struct UserIds {
|
||||
- uid: uid_t,
|
||||
- gid: gid_t,
|
||||
+ passwd: libc::passwd,
|
||||
+ group: libc::group,
|
||||
}
|
||||
|
||||
pub(crate) fn get_gid() -> gid_t {
|
||||
@@ -47,14 +46,14 @@ impl TryFrom<&str> for UserIds {
|
||||
let group = parts[1];
|
||||
|
||||
// Get gid from group name
|
||||
- let gid = if let Ok(g_cstr) = CString::new(group.as_bytes()) {
|
||||
+ let grnam = if let Ok(g_cstr) = CString::new(group.as_bytes()) {
|
||||
let p = unsafe { libc::getgrnam(g_cstr.as_ptr()) };
|
||||
if p.is_null() {
|
||||
let e = io::Error::last_os_error();
|
||||
error!("Could not get group {}: {}", group, e);
|
||||
return Err(Error::Conversion(e.to_string()));
|
||||
}
|
||||
- unsafe { (*p).gr_gid }
|
||||
+ unsafe { (*p) }
|
||||
} else {
|
||||
return Err(Error::Conversion(format!(
|
||||
"Failed to convert {} to CString",
|
||||
@@ -63,14 +62,14 @@ impl TryFrom<&str> for UserIds {
|
||||
};
|
||||
|
||||
// Get uid from user name
|
||||
- let uid = if let Ok(u_cstr) = CString::new(user.as_bytes()) {
|
||||
+ let passwd = if let Ok(u_cstr) = CString::new(user.as_bytes()) {
|
||||
let p = unsafe { libc::getpwnam(u_cstr.as_ptr()) };
|
||||
if p.is_null() {
|
||||
let e = io::Error::last_os_error();
|
||||
error!("Could not get user {}: {}", user, e);
|
||||
return Err(Error::Conversion(e.to_string()));
|
||||
}
|
||||
- unsafe { (*p).pw_uid }
|
||||
+ unsafe { (*p) }
|
||||
} else {
|
||||
return Err(Error::Conversion(format!(
|
||||
"Failed to convert {} to CString",
|
||||
@@ -78,7 +77,10 @@ impl TryFrom<&str> for UserIds {
|
||||
)));
|
||||
};
|
||||
|
||||
- Ok(UserIds { uid, gid })
|
||||
+ Ok(UserIds {
|
||||
+ passwd,
|
||||
+ group: grnam,
|
||||
+ })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,22 +90,51 @@ impl TryFrom<&str> for UserIds {
|
||||
pub(crate) fn run_as(user_group: &str) -> Result<()> {
|
||||
let ids: UserIds = user_group.try_into()?;
|
||||
|
||||
- // Drop supplementary groups
|
||||
- if unsafe { libc::setgroups(0, ptr::null()) } != 0 {
|
||||
+ // Set gid
|
||||
+ if unsafe { libc::setgid(ids.group.gr_gid) } != 0 {
|
||||
let e = io::Error::last_os_error();
|
||||
- error!("Could not drop supplementary groups: {}", e);
|
||||
+ error!("Could not set group id: {}", e);
|
||||
return Err(Error::Permission);
|
||||
}
|
||||
|
||||
- // Set gid
|
||||
- if unsafe { libc::setgid(ids.gid) } != 0 {
|
||||
+ // Get list of supplementary groups
|
||||
+ let mut sup_groups: [gid_t; 32] = [0u32; 32];
|
||||
+ let mut ngroups: c_int = 32;
|
||||
+ if unsafe {
|
||||
+ libc::getgrouplist(
|
||||
+ ids.passwd.pw_name,
|
||||
+ ids.group.gr_gid,
|
||||
+ sup_groups.as_mut_ptr(),
|
||||
+ &mut ngroups,
|
||||
+ )
|
||||
+ } < 0
|
||||
+ {
|
||||
+ // Allocate a Vec and try again
|
||||
+ let mut sup_groups: Vec<gid_t> = Vec::with_capacity(ngroups as usize);
|
||||
+ if unsafe {
|
||||
+ libc::getgrouplist(
|
||||
+ ids.passwd.pw_name,
|
||||
+ ids.group.gr_gid,
|
||||
+ sup_groups.as_mut_ptr(),
|
||||
+ &mut ngroups,
|
||||
+ )
|
||||
+ } < 0
|
||||
+ {
|
||||
+ error!("Could not get list of supplementary groups");
|
||||
+ return Err(Error::Permission);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Set supplementary groups
|
||||
+ if unsafe { libc::setgroups(ngroups as usize, sup_groups.as_ptr()) } != 0
|
||||
+ {
|
||||
let e = io::Error::last_os_error();
|
||||
- error!("Could not set group id: {}", e);
|
||||
+ error!("Could not set supplementary groups: {}", e);
|
||||
return Err(Error::Permission);
|
||||
}
|
||||
|
||||
// Set uid
|
||||
- if unsafe { libc::setuid(ids.uid) } != 0 {
|
||||
+ if unsafe { libc::setuid(ids.passwd.pw_uid) } != 0 {
|
||||
let e = io::Error::last_os_error();
|
||||
error!("Could not set user id: {}", e);
|
||||
return Err(Error::Permission);
|
||||
@@ -126,9 +157,12 @@ pub(crate) fn chown(user_group: &str, path: &Path) -> Result<()> {
|
||||
return Err(Error::Permission);
|
||||
}
|
||||
|
||||
- // change directory owner to root
|
||||
+ // change directory owner
|
||||
let c_path = CString::new(path.as_os_str().as_bytes())?;
|
||||
- if unsafe { libc::chown(c_path.as_ptr(), ids.uid, ids.gid) } != 0 {
|
||||
+ if unsafe {
|
||||
+ libc::chown(c_path.as_ptr(), ids.passwd.pw_uid, ids.group.gr_gid)
|
||||
+ } != 0
|
||||
+ {
|
||||
error!("Failed to change file {} owner.", path.display());
|
||||
return Err(Error::Permission);
|
||||
}
|
||||
20
rust-keylime-show-path-missing-cert.patch
Normal file
20
rust-keylime-show-path-missing-cert.patch
Normal file
@ -0,0 +1,20 @@
|
||||
--- a/src/main.rs 2022-06-28 16:54:37.559307146 +0200
|
||||
+++ b/src/main.rs 2022-06-28 17:37:39.512350575 +0200
|
||||
@@ -512,7 +512,16 @@
|
||||
let ssl_context;
|
||||
if config.mtls_enabled {
|
||||
let keylime_ca_cert =
|
||||
- crypto::load_x509(Path::new(&config.keylime_ca_path))?;
|
||||
+ match crypto::load_x509(Path::new(&config.keylime_ca_path)) {
|
||||
+ Ok(t) => Ok(t),
|
||||
+ Err(e) => {
|
||||
+ error!(
|
||||
+ "Certificate not installed: {}",
|
||||
+ config.keylime_ca_path
|
||||
+ );
|
||||
+ Err(e)
|
||||
+ }
|
||||
+ }?;
|
||||
|
||||
cert = crypto::generate_x509(&nk_priv, &config.agent_uuid)?;
|
||||
mtls_cert = Some(&cert);
|
||||
2
sources
2
sources
@ -1,2 +1,2 @@
|
||||
SHA512 (rust-keylime-0.1.0~20220603gitaed51c7-vendor.tar.xz) = 591a378ff4c70767bd54f998ecd117ffc65e72c48900f69cb83ef57bfb2abe1afb6652e0cc2810c1c92ddcdbe17147c2cfc16a6c846bd46781c09c5db3748ea6
|
||||
SHA512 (rust-keylime-0.1.0~20220603gitaed51c7.tar.gz) = 0a045b0caa13a582a1270428edb49a7e20cc7df15b749458a9ddb2b84c05f240225d9e876a0cc082978dc5b52f7e0175cbbc3b937edd1ffed68e252be3ea17f8
|
||||
SHA512 (rust-keylime-0.1.0~20220603gitaed51c7-vendor.tar.xz) = 7c6c885debeed18ea7670b486ceb2b72a49d3cf4d8730e9489ad719c539e9a1229eaa8cac1b5d5e2ea96a888d5e61146432ea5aca06f0d9a0c91de160a91d581
|
||||
|
||||
Loading…
Reference in New Issue
Block a user