diff --git a/keylime-agent-rust.spec b/keylime-agent-rust.spec index 7686e88..1bd1b6a 100644 --- a/keylime-agent-rust.spec +++ b/keylime-agent-rust.spec @@ -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 diff --git a/rust-keylime-fix-metadata.diff b/rust-keylime-adjust-features.patch similarity index 82% rename from rust-keylime-fix-metadata.diff rename to rust-keylime-adjust-features.patch index bcd5e31..2d68c2c 100644 --- a/rust-keylime-fix-metadata.diff +++ b/rust-keylime-adjust-features.patch @@ -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 = [] diff --git a/rust-keylime-descriptive-error-messages.patch b/rust-keylime-descriptive-error-messages.patch new file mode 100644 index 0000000..63172ef --- /dev/null +++ b/rust-keylime-descriptive-error-messages.patch @@ -0,0 +1,43 @@ +From e20b936fc9d92ae05406cb86471d3e6fba823b7f Mon Sep 17 00:00:00 2001 +From: Anderson Toshiyuki Sasaki +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 +--- + 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), diff --git a/rust-keylime-drop-dependencies.patch b/rust-keylime-drop-dependencies.patch new file mode 100644 index 0000000..c1b9973 --- /dev/null +++ b/rust-keylime-drop-dependencies.patch @@ -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 +Date: Tue, 17 May 2022 18:56:50 +0200 +Subject: [PATCH 3/3] Drop unused dependency flate2 + +Signed-off-by: Anderson Toshiyuki Sasaki +--- + 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 + diff --git a/rust-keylime-set-supplementary-groups.patch b/rust-keylime-set-supplementary-groups.patch new file mode 100644 index 0000000..eba875a --- /dev/null +++ b/rust-keylime-set-supplementary-groups.patch @@ -0,0 +1,162 @@ +From 4ec807b1bbcfaa67f85d0c2659b1f439c2f540b4 Mon Sep 17 00:00:00 2001 +From: Anderson Toshiyuki Sasaki +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 +--- + 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 = 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); + } diff --git a/rust-keylime-show-path-missing-cert.patch b/rust-keylime-show-path-missing-cert.patch new file mode 100644 index 0000000..9ad01e7 --- /dev/null +++ b/rust-keylime-show-path-missing-cert.patch @@ -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); diff --git a/sources b/sources index 0e86977..0d30136 100644 --- a/sources +++ b/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