Fix setting a certificate's expiration time.
- When setting a certificate's expiration time, we update each user ID's self signature. If a user ID is revoked, creating a new self signature will "unrevoke it." - Skip user IDs that are revoked.
This commit is contained in:
parent
9a2f2bc72b
commit
7292c6c347
@ -8,6 +8,7 @@ use openpgp::Packet;
|
||||
use openpgp::Result;
|
||||
use openpgp::packet::signature::SignatureBuilder;
|
||||
use openpgp::serialize::Serialize;
|
||||
use openpgp::types::RevocationStatus;
|
||||
use openpgp::types::SignatureType;
|
||||
|
||||
use sequoia_cert_store::StoreUpdate;
|
||||
@ -211,6 +212,14 @@ pub fn expire(sq: Sq,
|
||||
.into());
|
||||
|
||||
for uidb in key.userids() {
|
||||
if let RevocationStatus::Revoked(_)
|
||||
= uidb.revocation_status(&policy, sq.time)
|
||||
{
|
||||
// The user ID is revoked. Skip it. (Adding a new
|
||||
// self signature would actually "unrevoke it"!)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Use the binding signature that is valid under our
|
||||
// policy as of the reference time. If there is none,
|
||||
// fall back to the most recent binding signature.
|
||||
|
46
tests/data/keys/retired-userid.pgp
Normal file
46
tests/data/keys/retired-userid.pgp
Normal file
@ -0,0 +1,46 @@
|
||||
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
xVgEZwO0RRYJKwYBBAHaRw8BAQdAZjrkH1DpWMgczW43IeeuysVtjpOhwBpXQ5Xj
|
||||
to/2ShMAAP9OCQJbRPqvNTKWXWBcZVZlmvPokd14Ff2v67uAbWEV+xD2wsALBB8W
|
||||
CgB9BYJnA7RFAwsJBwkQBqoVMs4U6xdHFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMu
|
||||
c2VxdW9pYS1wZ3Aub3JnTLsgsDSu/rX2MGMh7RC4eUZBVzLaAQPloN3M4xCiyHcD
|
||||
FQoIApsBAh4BFiEE1SzYOi2qSF8Ny5IdBqoVMs4U6xcAAK+UAP0RHrsILZZXSV15
|
||||
9SdHJ4xnr/yqvtP3hcQnOpdNFKxcagD9HNxJ4SkuDEWFmp/JejmDTxMgtdAzoJLq
|
||||
UtgZDt8YnwTNHVJldGlyZWQgPHJldGlyZWRAZXhhbXBsZS5vcmc+wsAEBDAWCgB2
|
||||
BYJnA7SJCRAGqhUyzhTrF0cUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lh
|
||||
LXBncC5vcmf2PFzojFfINLZs3q1P/b53b0k/Y35H/95k0o6iDQdrywYdIGxlZnQW
|
||||
IQTVLNg6LapIXw3Lkh0GqhUyzhTrFwAAdUYA/iDTlOfcu2HA82VDE4i6xTB+Oh7w
|
||||
BmfmHkgK+pTxiFE/AQD8Q10w6SdIirHSlo/xgHAUVy5ojgYRW7rG5LlyN6aJC8LA
|
||||
DgQTFgoAgAWCZwO0RQMLCQcJEAaqFTLOFOsXRxQAAAAAAB4AIHNhbHRAbm90YXRp
|
||||
b25zLnNlcXVvaWEtcGdwLm9yZ+UQ3ptf6d63vVVCnviqQs98FNS5XAfgZeachSSc
|
||||
1tJpAxUKCAKZAQKbAQIeARYhBNUs2DotqkhfDcuSHQaqFTLOFOsXAAAKxwD7BKhG
|
||||
949gCBc8sDPTwDRXMMAQkdPWD/fV/ywwKFj9SPUBAJ0qSiQEGrxZ3X1X28qPNjve
|
||||
REgSfxw5U4Vl5XzC/bwNx1gEZwO0RRYJKwYBBAHaRw8BAQdAezORkfu3nAqOKCqC
|
||||
mjrO73ehaw6HIaJIxbZTTNwFtIYAAP9+Ooiq3Xun7A0/ied9T7+3Lr9ZSjbCT3wB
|
||||
kMqX4Nm21BJawsC/BBgWCgExBYJnA7RFCRAGqhUyzhTrF0cUAAAAAAAeACBzYWx0
|
||||
QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmfKdpsOde91lyv0LhUZCvMME+hfyZtv
|
||||
z88ALXW+7mQZeQKbAr6gBBkWCgBvBYJnA7RFCRCCljX1nvZ6mkcUAAAAAAAeACBz
|
||||
YWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmfXL32w4PiEuxXAiL/VBW+cbxyZ
|
||||
UiZ/j5WfLq+9/MZUcBYhBERsLdr0B2trfsISzoKWNfWe9nqaAACnAAEAoCr/cbSe
|
||||
aG2eAAnyn8tZY1VJFFVzduWcO+oKk7XIMhQA/RSA+gb0uSwDsH/snnpxULQCJuDr
|
||||
+otd5r0MyhL6WW0IFiEE1SzYOi2qSF8Ny5IdBqoVMs4U6xcAAPnZAP9Z0EqNxX9f
|
||||
Z610/JLpnpJWzYrZYlvbIlUIlwds4l4xGgD9GJbK3c0rbNYGWqm51aeedHS1BmLK
|
||||
n1KjW+lLop3X5wvHWARnA7RFFgkrBgEEAdpHDwEBB0COwpiN37K6FcH40Fm2/BdC
|
||||
uaWDrxYMuyXlH3UKJKjlnwABAJ0/hmHcrtiSGTtjzNstDQ+8USvSV4W7MctRVPzu
|
||||
N3JsD6DCwL8EGBYKATEFgmcDtEUJEAaqFTLOFOsXRxQAAAAAAB4AIHNhbHRAbm90
|
||||
YXRpb25zLnNlcXVvaWEtcGdwLm9yZ3eu97UOdiR0MdJd+gnOZIRkRKJXY9A/nIc7
|
||||
hwn2R1LQApsgvqAEGRYKAG8FgmcDtEUJEDcAT+Z1QziSRxQAAAAAAB4AIHNhbHRA
|
||||
bm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZ2j6uz67+2FvisNp0mxNaNqDh/XpU6LD
|
||||
TmUTTjndRe/WFiEEVzRklk1STXMrQLegNwBP5nVDOJIAANxBAQD9VRzC1xKPnDkY
|
||||
AYKkA7zz3A5mJwlamRKe607jXIqugQEAsad3jZAKJbsSN3Z6+xv+rRsGPNWOdvV0
|
||||
X2M77TLhAQoWIQTVLNg6LapIXw3Lkh0GqhUyzhTrFwAAoaEA/1hOf5A2H9kzh9/I
|
||||
5jsI4QbNQiXSnxS18y2iHUMh51RqAQC8vQHmYzWRdsItefTDtisb6EI05Adp3CYV
|
||||
Hp8/5txQD8ddBGcDtEUSCisGAQQBl1UBBQEBB0C0SYKst8THzLcVR3OujHCHPEGq
|
||||
3hF3DCWv4cgN982OYgMBCAcAAP9ShKZnLreaqYEY/9MacuycqExHTtvtFCOgG1wg
|
||||
qSySIA/PwsAABBgWCgByBYJnA7RFCRAGqhUyzhTrF0cUAAAAAAAeACBzYWx0QG5v
|
||||
dGF0aW9ucy5zZXF1b2lhLXBncC5vcmd+zDJndidkbeOVTpYKArOAoTOIXtK4Zs4T
|
||||
Lt5JggFPGwKbDBYhBNUs2DotqkhfDcuSHQaqFTLOFOsXAACEqgD+MdCsDiVbO2lh
|
||||
iN+PhIFkiGI5lovnxHxuYLiggfTkaMMBAONLbEFbzLd0vAMxY20hEU01Uw4bSKMm
|
||||
K0ERWuHkbzoL
|
||||
=71x1
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
@ -1,9 +1,11 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use sequoia_openpgp as openpgp;
|
||||
use openpgp::parse::Parse;
|
||||
use openpgp::Cert;
|
||||
use openpgp::cert::amalgamation::ValidAmalgamation;
|
||||
use openpgp::Result;
|
||||
use sequoia_openpgp as openpgp;
|
||||
use openpgp::types::RevocationStatus;
|
||||
|
||||
use super::common::STANDARD_POLICY;
|
||||
use super::common::Sq;
|
||||
@ -234,7 +236,7 @@ fn unbound_userid() {
|
||||
None,
|
||||
updated_path.as_path(),
|
||||
true)
|
||||
.expect("sq key expire should suceed");
|
||||
.expect("sq key expire should succeed");
|
||||
|
||||
let vc = updated.with_policy(STANDARD_POLICY, sq.now())
|
||||
.expect("valid cert");
|
||||
@ -242,3 +244,50 @@ fn unbound_userid() {
|
||||
assert_eq!(expiration,
|
||||
Some(sq.now() + std::time::Duration::new(24 * 60 * 60, 0)));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn revoked_userid() {
|
||||
// Make sure we can extend the expiration time of a certificate
|
||||
// that includes a revoked user ID (i.e., a user ID without a self
|
||||
// signature), and make sure we DON'T make the user ID valid.
|
||||
|
||||
let sq = Sq::new();
|
||||
|
||||
let cert_path = sq.test_data()
|
||||
.join("keys")
|
||||
.join("retired-userid.pgp");
|
||||
|
||||
let cert = Cert::from_file(&cert_path).expect("can read");
|
||||
let vc = cert.with_policy(STANDARD_POLICY, sq.now())
|
||||
.expect("valid cert");
|
||||
// It shouldn't be expired yet.
|
||||
assert!(vc.primary_key().key_expiration_time().is_none());
|
||||
|
||||
let ua = vc.userids().next().expect("have a user ID");
|
||||
if let RevocationStatus::Revoked(_) = ua.revocation_status() {
|
||||
} else {
|
||||
panic!("User ID should be revoked, but isn't.");
|
||||
};
|
||||
|
||||
// Set it to expire in a day.
|
||||
let updated_path = sq.scratch_file("updated");
|
||||
let updated = sq.key_expire(cert_path,
|
||||
"1d",
|
||||
None,
|
||||
updated_path.as_path(),
|
||||
true)
|
||||
.expect("sq key expire should succeed");
|
||||
|
||||
let vc = updated.with_policy(STANDARD_POLICY, sq.now())
|
||||
.expect("valid cert");
|
||||
let expiration = vc.primary_key().key_expiration_time();
|
||||
assert_eq!(expiration,
|
||||
Some(sq.now() + std::time::Duration::new(24 * 60 * 60, 0)));
|
||||
|
||||
let ua = vc.userids().next().expect("have a user ID");
|
||||
if let RevocationStatus::Revoked(_) = ua.revocation_status() {
|
||||
} else {
|
||||
panic!("User ID should be revoked, but isn't.");
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user