bjorn/ocsp/
processing.rs

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}