1use chrono::prelude::*;
2
3pub type OCSPClient = crate::cert_order::ocsp_client::OcspClient<tonic::transport::Channel>;
4
5pub async fn handle_ocsp<'a>(req: &'a [u8], ocsp_issuers: &'a super::issuers::OCSPIssuers<'_>) -> super::types::OCSPResponse<'a> {
6 let req = match super::types::parse_ocsp_req(&req) {
7 Ok(r) => r,
8 Err(e) => return e
9 };
10
11 if req.request.requests.len() < 1 {
12 return super::types::OCSPResponse {
13 status: super::types::OCSPResponseStatus::MalformedRequest,
14 response: None,
15 };
16 }
17
18 if let Some(nonce) = req.request.nonce {
19 if nonce.len() == 0 || nonce.len() > 32 {
20 return super::types::OCSPResponse {
21 status: super::types::OCSPResponseStatus::MalformedRequest,
22 response: None,
23 };
24 }
25 }
26
27 if let Some(acceptable_responses) = req.request.acceptable_responses {
28 if !acceptable_responses.contains(&super::types::OCSPResponseTypeTag::BasicResponse) {
29 return super::types::OCSPResponse {
30 status: super::types::OCSPResponseStatus::MalformedRequest,
31 response: None,
32 };
33 }
34 }
35
36 let first_request = req.request.requests.get(0).unwrap();
37 let first_issuer = match ocsp_issuers.find_issuer(&first_request.cert_id) {
38 Some(i) => i,
39 None => return super::types::OCSPResponse {
40 status: super::types::OCSPResponseStatus::Unauthorized,
41 response: None,
42 }
43 };
44
45 for cert_req in &req.request.requests[1..] {
46 let ocsp_issuer = ocsp_issuers.find_issuer(&cert_req.cert_id);
47 match ocsp_issuer {
48 Some(i) => {
49 if i.cert_id != first_issuer.cert_id {
50 return super::types::OCSPResponse {
51 status: super::types::OCSPResponseStatus::MalformedRequest,
52 response: None,
53 };
54 }
55 }
56 None => return super::types::OCSPResponse {
57 status: super::types::OCSPResponseStatus::Unauthorized,
58 response: None,
59 }
60 }
61 }
62
63 let mut single_responses = vec![];
64
65 for cert_req in req.request.requests {
66 let mut client = first_issuer.grpc_client.clone();
67 let check_cert_resp = match client.check_cert(crate::cert_order::CheckCertRequest {
68 issuer_id: first_issuer.cert_id.clone(),
69 serial_number: cert_req.cert_id.serial_number.to_vec(),
70 }).await {
71 Ok(r) => r.into_inner(),
72 Err(e) => {
73 warn!("Unable to check certificate status: {:?}", e);
74 return super::types::OCSPResponse {
75 status: super::types::OCSPResponseStatus::InternalError,
76 response: None,
77 };
78 }
79 };
80 single_responses.push(super::types::SingleOCSPResponse {
81 cert_id: cert_req.cert_id.clone(),
82 cert_status: match crate::cert_order::CertStatus::try_from(check_cert_resp.status) {
83 Ok(crate::cert_order::CertStatus::CertGood) => super::types::CertStatus::Good,
84 Ok(crate::cert_order::CertStatus::CertUnknown) => super::types::CertStatus::Unknown,
85 Ok(crate::cert_order::CertStatus::CertRevoked) => super::types::CertStatus::Revoked(super::types::RevokedInfo {
86 revocation_time: match crate::util::proto_to_chrono(check_cert_resp.revocation_timestamp) {
87 Some(t) => t,
88 None => return super::types::OCSPResponse {
89 status: super::types::OCSPResponseStatus::InternalError,
90 response: None,
91 }
92 },
93 revocation_reason: match crate::cert_order::RevocationReason::try_from(check_cert_resp.revocation_reason) {
94 Err(_) => None,
95 Ok(crate::cert_order::RevocationReason::RevocationUnknown) => None,
96 Ok(crate::cert_order::RevocationReason::RevocationUnspecified) => Some(super::types::RevocationReason::Unspecified),
97 Ok(crate::cert_order::RevocationReason::RevocationKeyCompromise) => Some(super::types::RevocationReason::KeyCompromise),
98 Ok(crate::cert_order::RevocationReason::RevocationCaCompromise) => Some(super::types::RevocationReason::CACompromise),
99 Ok(crate::cert_order::RevocationReason::RevocationAffiliationChanged) => Some(super::types::RevocationReason::AffiliationChanged),
100 Ok(crate::cert_order::RevocationReason::RevocationSuperseded) => Some(super::types::RevocationReason::Superseded),
101 Ok(crate::cert_order::RevocationReason::RevocationCessationOfOperation) => Some(super::types::RevocationReason::CessationOfOperation),
102 Ok(crate::cert_order::RevocationReason::RevocationCertificateHold) => Some(super::types::RevocationReason::CertificateHold),
103 Ok(crate::cert_order::RevocationReason::RevocationRemoveFromCrl) => Some(super::types::RevocationReason::RemoveFromCRL),
104 Ok(crate::cert_order::RevocationReason::RevocationPrivilegeWithdrawn) => Some(super::types::RevocationReason::PrivilegeWithdrawn),
105 Ok(crate::cert_order::RevocationReason::RevocationAaCompromise) => Some(super::types::RevocationReason::AACompromise),
106 },
107 }),
108 Ok(crate::cert_order::CertStatus::CertUnissued) => super::types::CertStatus::Revoked(super::types::RevokedInfo {
109 revocation_time: Utc.timestamp_opt(0, 0).unwrap(),
110 revocation_reason: Some(super::types::RevocationReason::CertificateHold),
111 }),
112 Err(_) => super::types::CertStatus::Unknown,
113 },
114 this_update: crate::util::proto_to_chrono(check_cert_resp.this_update).unwrap_or_else(Utc::now),
115 next_update: crate::util::proto_to_chrono(check_cert_resp.next_update),
116 archive_cutoff: crate::util::proto_to_chrono(check_cert_resp.archive_cutoff),
117 invalidity_date: crate::util::proto_to_chrono(check_cert_resp.invalidity_date),
118 });
119 println!("{:?}", single_responses);
120 }
121
122 super::types::OCSPResponse {
123 status: super::types::OCSPResponseStatus::Successful,
124 response: Some(super::types::OCSPResponseType::BasicResponse(super::types::BasicOCSPResponse {
125 produced_at: Utc::now(),
126 issuer: &first_issuer,
127 responses: single_responses,
128 nonce: req.request.nonce,
129 })),
130 }
131}