Skip to content

Commit

Permalink
Ensure that we return an error when verifying signatures on a package
Browse files Browse the repository at this point in the history
with no signatures
  • Loading branch information
dralley committed Jun 6, 2023
1 parent a237377 commit ef2d8c2
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 46 deletions.
6 changes: 6 additions & 0 deletions src/rpm/headers/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ where
Ok(())
}

pub fn entry_is_present(&self, tag: T) -> bool {
self.index_entries
.iter()
.any(|entry| entry.tag == tag.to_u32())
}

pub(crate) fn find_entry_or_err(&self, tag: T) -> Result<&IndexEntry<T>, RPMError> {
self.index_entries
.iter()
Expand Down
154 changes: 109 additions & 45 deletions src/rpm/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use crate::constants::*;
use crate::errors::*;
#[cfg(feature = "signature-meta")]
use crate::signature;
#[cfg(feature = "signature-pgp")]
use crate::signature::pgp::Verifier;
use crate::CompressionType;
#[cfg(feature = "signature-meta")]
use std::io::Read;
Expand Down Expand Up @@ -148,7 +150,42 @@ impl RPMPackage {
Ok(())
}

// @todo: a function that returns the key ID of the key used to sign this package would be useful
/// Return the key id (issuer) of the signature
#[cfg(feature = "signature-pgp")]
pub fn signature_key_id(&self) -> Result<Option<String>, RPMError> {
let rsa_sig = &self
.metadata
.signature
.get_entry_data_as_binary(IndexSignatureTag::RPMSIGTAG_RSA);
if let Ok(rsa_sig) = rsa_sig {
return Ok(Verifier::parse_signature(rsa_sig)?
.issuer()
.map(hex::encode));
}

let eddsa_sig = &self
.metadata
.signature
.get_entry_data_as_binary(IndexSignatureTag::RPMSIGTAG_DSA);
if let Ok(eddsa_sig) = eddsa_sig {
return Ok(Verifier::parse_signature(eddsa_sig)?
.issuer()
.map(hex::encode));
}

let rpm_v3_sig = &self
.metadata
.signature
.get_entry_data_as_binary(IndexSignatureTag::RPMSIGTAG_PGP);
if let Ok(rpm_v3_sig) = rpm_v3_sig {
return Ok(Verifier::parse_signature(rpm_v3_sig)?
.issuer()
.map(hex::encode));
}

Ok(None)
}

// @todo: verify_signature() and verify_digests() don't provide any feedback on whether a signature/digest
// was present and verified or whether it was not present at all.

Expand All @@ -162,49 +199,78 @@ impl RPMPackage {
self.metadata.header.write(&mut header_bytes)?;
self.verify_digests()?;

match verifier.algorithm() {
signature::AlgorithmType::RSA => {
if let Ok(signature_header_and_content) = self
.metadata
.signature
.get_entry_data_as_binary(IndexSignatureTag::RPMSIGTAG_PGP)
{
signature::echo_signature(
"signature_header(header and content)",
signature_header_and_content,
);
let header_and_content_cursor =
io::Cursor::new(&header_bytes).chain(io::Cursor::new(&self.content));
verifier.verify(header_and_content_cursor, signature_header_and_content)?;
}

if let Ok(signature_header_only) = self
.metadata
.signature
.get_entry_data_as_binary(IndexSignatureTag::RPMSIGTAG_RSA)
{
signature::echo_signature(
"signature_header(header only)",
signature_header_only,
);
verifier.verify(header_bytes.as_slice(), signature_header_only)?;
}
}
signature::AlgorithmType::EdDSA => {
if let Ok(signature_header_only) = self
.metadata
.signature
.get_entry_data_as_binary(IndexSignatureTag::RPMSIGTAG_DSA)
{
signature::echo_signature(
"signature_header(header only)",
signature_header_only,
);
verifier.verify(header_bytes.as_slice(), signature_header_only)?;
}
}
let rsa_sig = &self
.metadata
.signature
.get_entry_data_as_binary(IndexSignatureTag::RPMSIGTAG_RSA);
let eddsa_sig = &self
.metadata
.signature
.get_entry_data_as_binary(IndexSignatureTag::RPMSIGTAG_DSA);
let rpm_v3_sig = &self
.metadata
.signature
.get_entry_data_as_binary(IndexSignatureTag::RPMSIGTAG_PGP);

if !rsa_sig.is_ok() && !eddsa_sig.is_ok() && !rpm_v3_sig.is_ok() {
return Err(RPMError::NoSignatureFound);
}

if let Ok(signature_header_only) = eddsa_sig {
signature::echo_signature("signature_header(header only)", signature_header_only);
verifier.verify(header_bytes.as_slice(), signature_header_only)?;
}

if let Ok(signature_header_and_content) = rpm_v3_sig {
signature::echo_signature(
"signature_header(header and content)",
signature_header_and_content,
);
let header_and_content_cursor =
io::Cursor::new(&header_bytes).chain(io::Cursor::new(&self.content));
verifier.verify(header_and_content_cursor, signature_header_and_content)?;
}

if let Ok(signature_header_only) = rsa_sig {
signature::echo_signature("signature_header(header only)", signature_header_only);
verifier.verify(header_bytes.as_slice(), signature_header_only)?;
}

// match verifier.algorithm() {
// signature::AlgorithmType::RSA => {
// if let Ok(signature_header_and_content) = rpm_v3_sig {
// signature::echo_signature(
// "signature_header(header and content)",
// signature_header_and_content,
// );
// let header_and_content_cursor =
// io::Cursor::new(&header_bytes).chain(io::Cursor::new(&self.content));
// verifier.verify(header_and_content_cursor, signature_header_and_content)?;
// }

// if let Ok(signature_header_only) = rsa_sig {
// signature::echo_signature(
// "signature_header(header only)",
// signature_header_only,
// );
// verifier.verify(header_bytes.as_slice(), signature_header_only)?;
// } else {
// return Err(RPMError::VerificationError { source: (), key_ref: () })
// }
// }
// signature::AlgorithmType::EdDSA => {
// if let Ok(signature_header_only) = eddsa_sig {
// signature::echo_signature(
// "signature_header(header only)",
// signature_header_only,
// );
// verifier.verify(header_bytes.as_slice(), signature_header_only)?;
// } else {
// return Err(RPMError::VerificationError { source: (), key_ref: () })
// }
// }
//}

Ok(())
}

Expand Down Expand Up @@ -326,9 +392,7 @@ impl RPMPackageMetadata {
/// Whether this package is a source package, or not
#[inline]
pub fn is_source_package(&self) -> bool {
self.header
.find_entry_or_err(IndexTag::RPMTAG_SOURCEPACKAGE)
.is_ok()
self.header.entry_is_present(IndexTag::RPMTAG_SOURCEPACKAGE)
}

/// Get the package name
Expand Down
2 changes: 1 addition & 1 deletion src/rpm/signature/pgp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ pub struct Verifier {
}

impl Verifier {
fn parse_signature(signature: &[u8]) -> Result<::pgp::packet::Signature, RPMError> {
pub(crate) fn parse_signature(signature: &[u8]) -> Result<::pgp::packet::Signature, RPMError> {
let mut cursor = Cursor::new(signature);
let parser = pgp::packet::PacketParser::new(&mut cursor);
let signature = parser
Expand Down

0 comments on commit ef2d8c2

Please sign in to comment.