1use diesel::prelude::*;
2use std::convert::TryInto;
3
4pub type OrderClient = crate::cert_order::ca_client::CaClient<tonic::transport::Channel>;
5
6pub(crate) async fn verify_eab(
7 client: &mut OrderClient, eab: &crate::types::jose::FlattenedJWS, req_url: &str,
8 acct_key: &openssl::pkey::PKeyRef<openssl::pkey::Public>,
9) -> super::ACMEResult<String> {
10 let (eab_header, eab_payload_bytes, eab_signature_bytes) = match super::jws::start_decode_jws(&eab) {
11 Ok(v) => v,
12 Err(e) => return Err(e.1)
13 };
14
15 if eab_header.nonce.is_some() {
16 return Err(crate::types::error::Error {
17 error_type: crate::types::error::Type::Malformed,
18 status: 400,
19 title: "Bad request".to_string(),
20 detail: "EAB must not contain a nonce".to_string(),
21 sub_problems: vec![],
22 instance: None,
23 identifier: None,
24 });
25 }
26
27 if eab_header.url != req_url {
28 return Err(crate::types::error::Error {
29 error_type: crate::types::error::Type::Malformed,
30 status: 400,
31 title: "Bad request".to_string(),
32 detail: "EAB URL must match outer URL".to_string(),
33 sub_problems: vec![],
34 instance: None,
35 identifier: None,
36 });
37 }
38
39 let eab_id = match eab_header.key {
40 crate::types::jose::JWKKey::KID(i) => i,
41 _ => return Err(crate::types::error::Error {
42 error_type: crate::types::error::Type::Malformed,
43 status: 400,
44 title: "Bad request".to_string(),
45 detail: "EAB must contain KID".to_string(),
46 sub_problems: vec![],
47 instance: None,
48 identifier: None,
49 })
50 };
51
52 let eab_jwk: openssl::pkey::PKey<openssl::pkey::Public> = (
53 &serde_json::from_slice::<crate::types::jose::JWK>(&eab_payload_bytes)
54 .map_err(|err| crate::types::error::Error {
55 error_type: crate::types::error::Type::Malformed,
56 status: 400,
57 title: "Invalid JWK".to_string(),
58 detail: format!("Invalid JWK header: '{}'", err),
59 sub_problems: vec![],
60 instance: None,
61 identifier: None,
62 })?
63 ).try_into().map_err(|err| crate::types::error::Error {
64 error_type: crate::types::error::Type::BadPublicKey,
65 status: 400,
66 title: "Invalid public key".to_string(),
67 detail: err,
68 sub_problems: vec![],
69 instance: None,
70 identifier: None,
71 })?;
72
73 if !acct_key.public_eq(&eab_jwk) {
74 return Err(crate::types::error::Error {
75 error_type: crate::types::error::Type::Malformed,
76 status: 400,
77 title: "Bad request".to_string(),
78 detail: "EAB key must match outer key".to_string(),
79 sub_problems: vec![],
80 instance: None,
81 identifier: None,
82 });
83 }
84
85 let signature_method: i32 = match eab_header.alg.as_str() {
86 "HS256" => crate::cert_order::EabSignatureMethod::Hs256.into(),
87 "HS384" => crate::cert_order::EabSignatureMethod::Hs384.into(),
88 "HS512" => crate::cert_order::EabSignatureMethod::Hs512.into(),
89 "HS1" => crate::cert_order::EabSignatureMethod::Hs1.into(),
90 _ => return Err(crate::types::error::Error {
91 error_type: crate::types::error::Type::BadSignatureAlgorithm,
92 status: 400,
93 title: "Bad request".to_string(),
94 detail: "Invalid EAB signature algorithm".to_string(),
95 sub_problems: vec![],
96 instance: None,
97 identifier: None,
98 })
99 };
100
101 let eab_result = crate::try_db_result!(client.validate_eab(crate::cert_order::ValidateEabRequest {
102 kid: eab_id.clone(),
103 signature_method,
104 signed_data: format!("{}.{}", eab.protected, eab.payload).into_bytes(),
105 signature: eab_signature_bytes,
106 }).await, "Failed to check EAB: {}")?;
107
108 if !eab_result.get_ref().valid {
109 return Err(crate::types::error::Error {
110 error_type: crate::types::error::Type::Malformed,
111 status: 403,
112 title: "Forbidden".to_string(),
113 detail: "EAB signature did not verify".to_string(),
114 sub_problems: vec![],
115 instance: None,
116 identifier: None,
117 });
118 }
119
120 Ok(eab_id)
121}
122
123pub(crate) fn map_rpc_identifier(i: crate::cert_order::Identifier) -> crate::types::identifier::Identifier {
124 crate::types::identifier::Identifier {
125 id_type: match crate::cert_order::IdentifierType::try_from(i.id_type) {
126 Err(_) => "".to_string(),
127 Ok(crate::cert_order::IdentifierType::UnknownIdentifier) => "".to_string(),
128 Ok(crate::cert_order::IdentifierType::DnsIdentifier) => crate::types::identifier::Type::DNS.to_string(),
129 Ok(crate::cert_order::IdentifierType::IpIdentifier) => crate::types::identifier::Type::IP.to_string(),
130 Ok(crate::cert_order::IdentifierType::EmailIdentifier) => crate::types::identifier::Type::Email.to_string(),
131 },
132 value: i.identifier,
133 }
134}
135
136pub(crate) fn rpc_error_to_problem(err: crate::cert_order::Error) -> crate::types::error::Error {
137 crate::types::error::Error {
138 error_type: match crate::cert_order::ErrorType::try_from(err.error_type) {
139 Err(_) => crate::types::error::Type::ServerInternal,
140 Ok(crate::cert_order::ErrorType::ServerInternalError) => crate::types::error::Type::ServerInternal,
141 Ok(crate::cert_order::ErrorType::AccountDoesNotExistError) => crate::types::error::Type::AccountDoesNotExist,
142 Ok(crate::cert_order::ErrorType::AlreadyRevokedError) => crate::types::error::Type::AlreadyRevoked,
143 Ok(crate::cert_order::ErrorType::BadCsrError) => crate::types::error::Type::BadCSR,
144 Ok(crate::cert_order::ErrorType::BadNonceError) => crate::types::error::Type::BadNonce,
145 Ok(crate::cert_order::ErrorType::BadPublicKeyError) => crate::types::error::Type::BadPublicKey,
146 Ok(crate::cert_order::ErrorType::BadRevocationReasonError) => crate::types::error::Type::BadRevocationReason,
147 Ok(crate::cert_order::ErrorType::BadSignatureAlgorithmError) => crate::types::error::Type::BadSignatureAlgorithm,
148 Ok(crate::cert_order::ErrorType::CaaError) => crate::types::error::Type::CAA,
149 Ok(crate::cert_order::ErrorType::CompoundError) => crate::types::error::Type::Compound,
150 Ok(crate::cert_order::ErrorType::ConnectionError) => crate::types::error::Type::Connection,
151 Ok(crate::cert_order::ErrorType::DnsError) => crate::types::error::Type::DNS,
152 Ok(crate::cert_order::ErrorType::ExternalAccountRequiredError) => crate::types::error::Type::ExternalAccountRequired,
153 Ok(crate::cert_order::ErrorType::IncorrectResponseError) => crate::types::error::Type::IncorrectResponse,
154 Ok(crate::cert_order::ErrorType::InvalidContactError) => crate::types::error::Type::InvalidContact,
155 Ok(crate::cert_order::ErrorType::MalformedError) => crate::types::error::Type::Malformed,
156 Ok(crate::cert_order::ErrorType::OrderNotReadyError) => crate::types::error::Type::OrderNotReady,
157 Ok(crate::cert_order::ErrorType::RateLimitedError) => crate::types::error::Type::RateLimited,
158 Ok(crate::cert_order::ErrorType::RejectedIdentifierError) => crate::types::error::Type::RejectedIdentifier,
159 Ok(crate::cert_order::ErrorType::TlsError) => crate::types::error::Type::TLS,
160 Ok(crate::cert_order::ErrorType::UnauthorizedError) => crate::types::error::Type::Unauthorized,
161 Ok(crate::cert_order::ErrorType::UnsupportedContactError) => crate::types::error::Type::UnsupportedContact,
162 Ok(crate::cert_order::ErrorType::UnsupportedIdentifierError) => crate::types::error::Type::UnsupportedIdentifier,
163 Ok(crate::cert_order::ErrorType::UserActionRequiredError) => crate::types::error::Type::UserActionRequired,
164 Ok(crate::cert_order::ErrorType::AutoRenewalCanceledError) => crate::types::error::Type::AutoRenewalCanceled,
165 Ok(crate::cert_order::ErrorType::AutoRenewalExpiredError) => crate::types::error::Type::AutoRenewalExpired,
166 Ok(crate::cert_order::ErrorType::AutoRenewalCancellationInvalidError) => crate::types::error::Type::AutoRenewalCancellationInvalid,
167 Ok(crate::cert_order::ErrorType::AutoRenewalRevocationNotSupportedError) => crate::types::error::Type::AutoRenewalRevocationNotSupported,
168 },
169 title: err.title,
170 status: err.status as u16,
171 detail: err.detail,
172 instance: err.instance,
173 sub_problems: err.sub_problems.into_iter().map(rpc_error_to_problem).collect(),
174 identifier: err.identifier.map(map_rpc_identifier),
175 }
176}
177
178pub(crate) fn unwrap_order_response(resp: crate::cert_order::OrderResponse) -> crate::acme::ACMEResult<crate::cert_order::Order> {
179 match resp.result {
180 Some(crate::cert_order::order_response::Result::Order(o)) => Ok(o),
181 Some(crate::cert_order::order_response::Result::Error(e)) => Err(
182 crate::util::error_list_to_result(
183 e.errors.into_iter().map(rpc_error_to_problem).collect(),
184 "Multiple errors make this order invalid".to_string(),
185 ).err().unwrap()
186 ),
187 None => Err(crate::internal_server_error!())
188 }
189}
190
191pub(crate) fn unwrap_authz_response(resp: crate::cert_order::AuthorizationResponse) -> crate::acme::ACMEResult<crate::cert_order::Authorization> {
192 match resp.result {
193 Some(crate::cert_order::authorization_response::Result::Authorization(a)) => Ok(a),
194 Some(crate::cert_order::authorization_response::Result::Error(e)) => Err(
195 crate::util::error_list_to_result(
196 e.errors.into_iter().map(rpc_error_to_problem).collect(),
197 "Multiple errors make this authorization invalid".to_string(),
198 ).err().unwrap()
199 ),
200 None => Err(crate::internal_server_error!())
201 }
202}
203
204pub(crate) fn unwrap_chall_response(resp: crate::cert_order::ChallengeResponse) -> crate::acme::ACMEResult<crate::cert_order::Challenge> {
205 match resp.result {
206 Some(crate::cert_order::challenge_response::Result::Challenge(a)) => Ok(a),
207 Some(crate::cert_order::challenge_response::Result::Error(e)) => Err(
208 crate::util::error_list_to_result(
209 e.errors.into_iter().map(rpc_error_to_problem).collect(),
210 "Multiple errors make this challenge invalid".to_string(),
211 ).err().unwrap()
212 ),
213 None => Err(crate::internal_server_error!())
214 }
215}
216
217pub(crate) async fn create_order(
218 client: &mut OrderClient, db: &crate::DBConn,
219 order: &crate::types::order::OrderCreate, account: &crate::acme::Account,
220) -> crate::acme::ACMEResult<(super::models::Order, crate::cert_order::Order)> {
221 let mut errors = vec![];
222
223 let mut identifiers = vec![];
224
225 for id in &order.identifiers {
226 let id_type = crate::types::identifier::Type::from_str(&id.id_type);
227 let grpc_id_type = match id_type {
228 Some(crate::types::identifier::Type::DNS) => crate::cert_order::IdentifierType::DnsIdentifier,
229 Some(crate::types::identifier::Type::IP) => crate::cert_order::IdentifierType::IpIdentifier,
230 Some(crate::types::identifier::Type::Email) => crate::cert_order::IdentifierType::EmailIdentifier,
231 None => {
232 errors.push(crate::types::error::Error {
233 error_type: crate::types::error::Type::UnsupportedIdentifier,
234 status: 400,
235 title: "Unsupported identifier".to_string(),
236 detail: format!("'{}' is not an identifier we support", id.id_type),
237 sub_problems: vec![],
238 instance: None,
239 identifier: Some(id.to_owned()),
240 });
241 continue;
242 }
243 };
244 identifiers.push(crate::cert_order::Identifier {
245 id_type: grpc_id_type.into(),
246 identifier: id.value.clone(),
247 });
248 }
249
250 crate::util::error_list_to_result(errors, "Multiple errors make this order invalid".to_string())?;
251
252 let order_result = crate::try_db_result!(client.create_order(crate::cert_order::CreateOrderRequest {
253 identifiers,
254 not_before: crate::util::chrono_to_proto(order.not_before),
255 not_after: crate::util::chrono_to_proto(order.not_after),
256 account_id: account.inner.id.to_string(),
257 eab_id: account.inner.eab_id.clone(),
258 }).await, "Failed to create order: {}")?;
259
260 let ca_order = unwrap_order_response(order_result.into_inner())?;
261
262 let db_order = super::models::Order {
263 id: uuid::Uuid::new_v4(),
264 account: account.inner.id,
265 ca_id: ca_order.id.clone(),
266 };
267
268 let db_order = crate::try_db_result!(db.run(move |c|
269 diesel::insert_into(super::schema::orders::dsl::orders)
270 .values(&db_order).get_result(c)
271 ).await,
272 "Unable to save order to database: {}"
273 )?;
274
275 Ok((db_order, ca_order))
276}
277
278pub(crate) async fn create_authz(
279 client: &mut OrderClient, db: &crate::DBConn,
280 authz: &crate::types::authorization::AuthorizationCreate, account: &crate::acme::Account,
281) -> crate::acme::ACMEResult<(super::models::Authorization, crate::cert_order::Authorization)> {
282 let grpc_id_type = match crate::types::identifier::Type::from_str(&authz.identifier.id_type) {
283 Some(crate::types::identifier::Type::DNS) => crate::cert_order::IdentifierType::DnsIdentifier,
284 Some(crate::types::identifier::Type::IP) => crate::cert_order::IdentifierType::IpIdentifier,
285 Some(crate::types::identifier::Type::Email) => crate::cert_order::IdentifierType::EmailIdentifier,
286 None => {
287 return Err(crate::types::error::Error {
288 error_type: crate::types::error::Type::UnsupportedIdentifier,
289 status: 400,
290 title: "Unsupported identifier".to_string(),
291 detail: format!("'{}' is not an identifier we support", authz.identifier.id_type),
292 sub_problems: vec![],
293 instance: None,
294 identifier: Some(authz.identifier.to_owned()),
295 });
296 }
297 };
298 let identifier = crate::cert_order::Identifier {
299 id_type: grpc_id_type.into(),
300 identifier: authz.identifier.value.clone(),
301 };
302
303 let authz_result = crate::try_db_result!(client.create_authorization(crate::cert_order::CreateAuthorizationRequest {
304 identifier: Some(identifier),
305 account_id: account.inner.id.to_string(),
306 eab_id: account.inner.eab_id.clone(),
307 }).await, "Failed to create authorization: {}")?;
308
309 let ca_authz = unwrap_authz_response(authz_result.into_inner())?;
310
311 let db_authz = super::models::Authorization {
312 id: uuid::Uuid::new_v4(),
313 account: account.inner.id,
314 ca_id: ca_authz.id.clone(),
315 };
316
317 let db_authz = crate::try_db_result!(db.run(move |c|
318 diesel::insert_into(super::schema::authorizations::dsl::authorizations)
319 .values(&db_authz).get_result(c)
320 ).await,
321 "Unable to save authorization to database: {}"
322 )?;
323
324 Ok((db_authz, ca_authz))
325}