You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
5.3 KiB

  1. use crate::account::contact::AccountContact;
  2. use crate::account::{Account, AccountEndpoint, AccountKey, ExternalAccount};
  3. use crate::storage::{account_files_exists, get_account_data, set_account_data, FileManager};
  4. use acme_common::crypto::KeyPair;
  5. use acme_common::error::Error;
  6. use serde::{Deserialize, Serialize};
  7. use std::collections::HashMap;
  8. use std::time::SystemTime;
  9. #[derive(Serialize, Deserialize, PartialEq, Debug)]
  10. pub struct ExternalAccountStorage {
  11. pub identifier: String,
  12. pub key: Vec<u8>,
  13. pub signature_algorithm: String,
  14. }
  15. impl ExternalAccountStorage {
  16. fn new(external_account: &ExternalAccount) -> Self {
  17. ExternalAccountStorage {
  18. identifier: external_account.identifier.to_owned(),
  19. key: external_account.key.to_owned(),
  20. signature_algorithm: external_account.signature_algorithm.to_string(),
  21. }
  22. }
  23. fn to_generic(&self) -> Result<ExternalAccount, Error> {
  24. Ok(ExternalAccount {
  25. identifier: self.identifier.to_owned(),
  26. key: self.key.to_owned(),
  27. signature_algorithm: self.signature_algorithm.parse()?,
  28. })
  29. }
  30. }
  31. #[derive(Serialize, Deserialize, PartialEq, Debug)]
  32. struct AccountKeyStorage {
  33. creation_date: SystemTime,
  34. key: Vec<u8>,
  35. signature_algorithm: String,
  36. }
  37. impl AccountKeyStorage {
  38. fn new(key: &AccountKey) -> Result<Self, Error> {
  39. Ok(AccountKeyStorage {
  40. creation_date: key.creation_date,
  41. key: key.key.private_key_to_der()?,
  42. signature_algorithm: key.signature_algorithm.to_string(),
  43. })
  44. }
  45. fn to_generic(&self) -> Result<AccountKey, Error> {
  46. Ok(AccountKey {
  47. creation_date: self.creation_date,
  48. key: KeyPair::from_der(&self.key)?,
  49. signature_algorithm: self.signature_algorithm.parse()?,
  50. })
  51. }
  52. }
  53. #[derive(Serialize, Deserialize, PartialEq, Debug)]
  54. struct AccountEndpointStorage {
  55. creation_date: SystemTime,
  56. account_url: String,
  57. orders_url: String,
  58. key_hash: Vec<u8>,
  59. contacts_hash: Vec<u8>,
  60. external_account_hash: Vec<u8>,
  61. }
  62. impl AccountEndpointStorage {
  63. fn new(account_endpoint: &AccountEndpoint) -> Self {
  64. AccountEndpointStorage {
  65. creation_date: account_endpoint.creation_date,
  66. account_url: account_endpoint.account_url.clone(),
  67. orders_url: account_endpoint.orders_url.clone(),
  68. key_hash: account_endpoint.key_hash.clone(),
  69. contacts_hash: account_endpoint.contacts_hash.clone(),
  70. external_account_hash: account_endpoint.external_account_hash.clone(),
  71. }
  72. }
  73. fn to_generic(&self) -> AccountEndpoint {
  74. AccountEndpoint {
  75. creation_date: self.creation_date,
  76. account_url: self.account_url.clone(),
  77. orders_url: self.orders_url.clone(),
  78. key_hash: self.key_hash.clone(),
  79. contacts_hash: self.contacts_hash.clone(),
  80. external_account_hash: self.external_account_hash.clone(),
  81. }
  82. }
  83. }
  84. #[derive(Serialize, Deserialize, PartialEq, Debug)]
  85. struct AccountStorage {
  86. name: String,
  87. endpoints: HashMap<String, AccountEndpointStorage>,
  88. contacts: Vec<(String, String)>,
  89. current_key: AccountKeyStorage,
  90. past_keys: Vec<AccountKeyStorage>,
  91. external_account: Option<ExternalAccountStorage>,
  92. }
  93. fn do_fetch(file_manager: &FileManager, name: &str) -> Result<Option<Account>, Error> {
  94. if account_files_exists(file_manager) {
  95. let data = get_account_data(file_manager)?;
  96. let obj: AccountStorage = bincode::deserialize(&data[..])
  97. .map_err(|e| Error::from(&e.to_string()).prefix(name))?;
  98. let endpoints = obj
  99. .endpoints
  100. .iter()
  101. .map(|(k, v)| (k.clone(), v.to_generic()))
  102. .collect();
  103. let contacts = obj
  104. .contacts
  105. .iter()
  106. .map(|(t, v)| AccountContact::new(t, v))
  107. .collect::<Result<Vec<AccountContact>, Error>>()?;
  108. let current_key = obj.current_key.to_generic()?;
  109. let past_keys = obj
  110. .past_keys
  111. .iter()
  112. .map(|k| k.to_generic())
  113. .collect::<Result<Vec<AccountKey>, Error>>()?;
  114. let external_account = match obj.external_account {
  115. Some(a) => Some(a.to_generic()?),
  116. None => None,
  117. };
  118. Ok(Some(Account {
  119. name: obj.name,
  120. endpoints,
  121. contacts,
  122. current_key,
  123. past_keys,
  124. file_manager: file_manager.clone(),
  125. external_account,
  126. }))
  127. } else {
  128. Ok(None)
  129. }
  130. }
  131. fn do_save(file_manager: &FileManager, account: &Account) -> Result<(), Error> {
  132. let endpoints: HashMap<String, AccountEndpointStorage> = account
  133. .endpoints
  134. .iter()
  135. .map(|(k, v)| (k.to_owned(), AccountEndpointStorage::new(v)))
  136. .collect();
  137. let contacts: Vec<(String, String)> = account
  138. .contacts
  139. .iter()
  140. .map(|c| (c.contact_type.to_string(), c.value.to_owned()))
  141. .collect();
  142. let past_keys = account
  143. .past_keys
  144. .iter()
  145. .map(AccountKeyStorage::new)
  146. .collect::<Result<Vec<AccountKeyStorage>, Error>>()?;
  147. let external_account = account
  148. .external_account
  149. .as_ref()
  150. .map(ExternalAccountStorage::new);
  151. let account_storage = AccountStorage {
  152. name: account.name.to_owned(),
  153. endpoints,
  154. contacts,
  155. current_key: AccountKeyStorage::new(&account.current_key)?,
  156. past_keys,
  157. external_account,
  158. };
  159. let encoded: Vec<u8> = bincode::serialize(&account_storage)
  160. .map_err(|e| Error::from(&e.to_string()).prefix(&account.name))?;
  161. set_account_data(file_manager, &encoded)
  162. }
  163. pub fn fetch(file_manager: &FileManager, name: &str) -> Result<Option<Account>, Error> {
  164. do_fetch(file_manager, name).map_err(|_| {
  165. format!(
  166. "account \"{}\": unable to load account file: file may be corrupted",
  167. name
  168. )
  169. .into()
  170. })
  171. }
  172. pub fn save(file_manager: &FileManager, account: &Account) -> Result<(), Error> {
  173. do_save(file_manager, account).map_err(|e| format!("unable to save account file: {}", e).into())
  174. }