From 3c173bcf13d4c60d6ccf5091d79284f4a0f09228 Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Sat, 19 Sep 2020 11:46:19 +0200 Subject: [PATCH] Create a new account if the external account has changed --- acmed/src/account.rs | 30 ++++++++++++++++++++++++++++++ acmed/src/account/storage.rs | 21 +++++++++++++++++++-- acmed/src/acme_proto/account.rs | 1 + 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/acmed/src/account.rs b/acmed/src/account.rs index 3ab5438..c68c9f4 100644 --- a/acmed/src/account.rs +++ b/acmed/src/account.rs @@ -70,6 +70,7 @@ pub struct AccountEndpoint { pub order_url: String, pub key_hash: Vec, pub contacts_hash: Vec, + pub external_account_hash: Vec, } impl AccountEndpoint { @@ -80,6 +81,7 @@ impl AccountEndpoint { order_url: String::new(), key_hash: Vec::new(), contacts_hash: Vec::new(), + external_account_hash: Vec::new(), } } } @@ -176,6 +178,7 @@ impl Account { Some(mut a) => { a.update_keys(key_type, signature_algorithm)?; a.contacts = contacts; + a.external_account = external_account.to_owned(); a } None => { @@ -208,6 +211,18 @@ impl Account { ) -> Result<(), Error> { let acc_ep = self.get_endpoint(&endpoint.name)?; if !acc_ep.account_url.is_empty() { + if let Some(ec) = &self.external_account { + let external_account_hash = hash_external_account(&ec); + if external_account_hash != acc_ep.external_account_hash { + let msg = format!( + "external account changed on endpoint \"{}\"", + &endpoint.name + ); + self.info(&msg); + register_account(endpoint, root_certs, self)?; + return Ok(()); + } + } let ct_hash = hash_contacts(&self.contacts); let key_hash = hash_key(&self.current_key)?; let contacts_changed = ct_hash != acc_ep.contacts_hash; @@ -257,6 +272,15 @@ impl Account { Ok(()) } + pub fn update_external_account_hash(&mut self, endpoint_name: &str) -> Result<(), Error> { + if let Some(ec) = &self.external_account { + let ec = ec.clone(); + let mut ep = self.get_endpoint_mut(endpoint_name)?; + ep.external_account_hash = hash_external_account(&ec); + } + Ok(()) + } + fn update_keys( &mut self, key_type: KeyType, @@ -295,3 +319,9 @@ fn hash_key(key: &AccountKey) -> Result, Error> { let pem = key.key.public_key_to_pem()?; Ok(HashFunction::Sha256.hash(&pem)) } + +fn hash_external_account(ec: &ExternalAccount) -> Vec { + let mut msg = ec.key.clone(); + msg.extend(ec.identifier.as_bytes()); + HashFunction::Sha256.hash(&msg) +} diff --git a/acmed/src/account/storage.rs b/acmed/src/account/storage.rs index 904ec60..2ae82ee 100644 --- a/acmed/src/account/storage.rs +++ b/acmed/src/account/storage.rs @@ -64,6 +64,7 @@ struct AccountEndpointStorage { order_url: String, key_hash: Vec, contacts_hash: Vec, + external_account_hash: Vec, } impl AccountEndpointStorage { @@ -74,6 +75,7 @@ impl AccountEndpointStorage { order_url: account_endpoint.order_url.clone(), key_hash: account_endpoint.key_hash.clone(), contacts_hash: account_endpoint.contacts_hash.clone(), + external_account_hash: account_endpoint.external_account_hash.clone(), } } @@ -84,6 +86,7 @@ impl AccountEndpointStorage { order_url: self.order_url.clone(), key_hash: self.key_hash.clone(), contacts_hash: self.contacts_hash.clone(), + external_account_hash: self.external_account_hash.clone(), } } } @@ -98,7 +101,7 @@ struct AccountStorage { external_account: Option, } -pub fn fetch(file_manager: &FileManager, name: &str) -> Result, Error> { +fn do_fetch(file_manager: &FileManager, name: &str) -> Result, Error> { if account_files_exists(file_manager) { let data = get_account_data(file_manager)?; let obj: AccountStorage = bincode::deserialize(&data[..]) @@ -137,7 +140,7 @@ pub fn fetch(file_manager: &FileManager, name: &str) -> Result, } } -pub fn save(file_manager: &FileManager, account: &Account) -> Result<(), Error> { +fn do_save(file_manager: &FileManager, account: &Account) -> Result<(), Error> { let endpoints: HashMap = account .endpoints .iter() @@ -169,3 +172,17 @@ pub fn save(file_manager: &FileManager, account: &Account) -> Result<(), Error> .map_err(|e| Error::from(&e.to_string()).prefix(&account.name))?; set_account_data(file_manager, &encoded) } + +pub fn fetch(file_manager: &FileManager, name: &str) -> Result, Error> { + do_fetch(file_manager, name).map_err(|_| { + format!( + "account \"{}\": unable to load account file: file may be corrupted", + name + ) + .into() + }) +} + +pub fn save(file_manager: &FileManager, account: &Account) -> Result<(), Error> { + do_save(file_manager, account).map_err(|e| format!("unable to save account file: {}", e).into()) +} diff --git a/acmed/src/acme_proto/account.rs b/acmed/src/acme_proto/account.rs index f0d32d5..8469192 100644 --- a/acmed/src/acme_proto/account.rs +++ b/acmed/src/acme_proto/account.rs @@ -57,6 +57,7 @@ pub fn register_account( account.set_order_url(&endpoint.name, &order_url)?; account.update_key_hash(&endpoint.name)?; account.update_contacts_hash(&endpoint.name)?; + account.update_external_account_hash(&endpoint.name)?; account.save()?; account.info(&format!( "account created on endpoint \"{}\"",