]> git.proxmox.com Git - cargo.git/blob - vendor/openssl-0.9.23/src/ocsp.rs
New upstream version 0.24.0
[cargo.git] / vendor / openssl-0.9.23 / src / ocsp.rs
1 use ffi;
2 use foreign_types::ForeignTypeRef;
3 use libc::{c_int, c_long, c_ulong};
4 use std::ptr;
5 use std::mem;
6
7 use {cvt, cvt_p};
8 use asn1::Asn1GeneralizedTimeRef;
9 use error::ErrorStack;
10 use hash::MessageDigest;
11 use stack::StackRef;
12 use x509::store::X509StoreRef;
13 use x509::{X509, X509Ref};
14
15 bitflags! {
16 pub struct Flag: c_ulong {
17 const FLAG_NO_CERTS = ffi::OCSP_NOCERTS;
18 const FLAG_NO_INTERN = ffi::OCSP_NOINTERN;
19 const FLAG_NO_CHAIN = ffi::OCSP_NOCHAIN;
20 const FLAG_NO_VERIFY = ffi::OCSP_NOVERIFY;
21 const FLAG_NO_EXPLICIT = ffi::OCSP_NOEXPLICIT;
22 const FLAG_NO_CA_SIGN = ffi::OCSP_NOCASIGN;
23 const FLAG_NO_DELEGATED = ffi::OCSP_NODELEGATED;
24 const FLAG_NO_CHECKS = ffi::OCSP_NOCHECKS;
25 const FLAG_TRUST_OTHER = ffi::OCSP_TRUSTOTHER;
26 const FLAG_RESPID_KEY = ffi::OCSP_RESPID_KEY;
27 const FLAG_NO_TIME = ffi::OCSP_NOTIME;
28 }
29 }
30
31 pub const RESPONSE_STATUS_SUCCESSFUL: OcspResponseStatus =
32 OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_SUCCESSFUL);
33 pub const RESPONSE_STATUS_MALFORMED_REQUEST: OcspResponseStatus =
34 OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_MALFORMEDREQUEST);
35 pub const RESPONSE_STATUS_INTERNAL_ERROR: OcspResponseStatus =
36 OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_INTERNALERROR);
37 pub const RESPONSE_STATUS_TRY_LATER: OcspResponseStatus =
38 OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_TRYLATER);
39 pub const RESPONSE_STATUS_SIG_REQUIRED: OcspResponseStatus =
40 OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_SIGREQUIRED);
41 pub const RESPONSE_STATUS_UNAUTHORIZED: OcspResponseStatus =
42 OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_UNAUTHORIZED);
43
44 pub const CERT_STATUS_GOOD: OcspCertStatus = OcspCertStatus(ffi::V_OCSP_CERTSTATUS_GOOD);
45 pub const CERT_STATUS_REVOKED: OcspCertStatus = OcspCertStatus(ffi::V_OCSP_CERTSTATUS_REVOKED);
46 pub const CERT_STATUS_UNKNOWN: OcspCertStatus = OcspCertStatus(ffi::V_OCSP_CERTSTATUS_UNKNOWN);
47
48 pub const REVOKED_STATUS_NO_STATUS: OcspRevokedStatus =
49 OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_NOSTATUS);
50 pub const REVOKED_STATUS_UNSPECIFIED: OcspRevokedStatus =
51 OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_UNSPECIFIED);
52 pub const REVOKED_STATUS_KEY_COMPROMISE: OcspRevokedStatus =
53 OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_KEYCOMPROMISE);
54 pub const REVOKED_STATUS_CA_COMPROMISE: OcspRevokedStatus =
55 OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_CACOMPROMISE);
56 pub const REVOKED_STATUS_AFFILIATION_CHANGED: OcspRevokedStatus =
57 OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_AFFILIATIONCHANGED);
58 pub const REVOKED_STATUS_SUPERSEDED: OcspRevokedStatus =
59 OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_SUPERSEDED);
60 pub const REVOKED_STATUS_CESSATION_OF_OPERATION: OcspRevokedStatus =
61 OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_CESSATIONOFOPERATION);
62 pub const REVOKED_STATUS_CERTIFICATE_HOLD: OcspRevokedStatus =
63 OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_CERTIFICATEHOLD);
64 pub const REVOKED_STATUS_REMOVE_FROM_CRL: OcspRevokedStatus =
65 OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_REMOVEFROMCRL);
66
67 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
68 pub struct OcspResponseStatus(c_int);
69
70 impl OcspResponseStatus {
71 pub fn from_raw(raw: c_int) -> OcspResponseStatus {
72 OcspResponseStatus(raw)
73 }
74
75 pub fn as_raw(&self) -> c_int {
76 self.0
77 }
78 }
79
80 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
81 pub struct OcspCertStatus(c_int);
82
83 impl OcspCertStatus {
84 pub fn from_raw(raw: c_int) -> OcspCertStatus {
85 OcspCertStatus(raw)
86 }
87
88 pub fn as_raw(&self) -> c_int {
89 self.0
90 }
91 }
92
93 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
94 pub struct OcspRevokedStatus(c_int);
95
96 impl OcspRevokedStatus {
97 pub fn from_raw(raw: c_int) -> OcspRevokedStatus {
98 OcspRevokedStatus(raw)
99 }
100
101 pub fn as_raw(&self) -> c_int {
102 self.0
103 }
104 }
105
106 pub struct Status<'a> {
107 /// The overall status of the response.
108 pub status: OcspCertStatus,
109 /// If `status` is `CERT_STATUS_REVOKED`, the reason for the revocation.
110 pub reason: OcspRevokedStatus,
111 /// If `status` is `CERT_STATUS_REVOKED`, the time at which the certificate was revoked.
112 pub revocation_time: Option<&'a Asn1GeneralizedTimeRef>,
113 /// The time that this revocation check was performed.
114 pub this_update: &'a Asn1GeneralizedTimeRef,
115 /// The time at which this revocation check expires.
116 pub next_update: &'a Asn1GeneralizedTimeRef,
117 }
118
119 impl<'a> Status<'a> {
120 /// Checks validity of the `this_update` and `next_update` fields.
121 ///
122 /// The `nsec` parameter specifies an amount of slack time that will be used when comparing
123 /// those times with the current time to account for delays and clock skew.
124 ///
125 /// The `maxsec` parameter limits the maximum age of the `this_update` parameter to prohibit
126 /// very old responses.
127 pub fn check_validity(&self, nsec: u32, maxsec: Option<u32>) -> Result<(), ErrorStack> {
128 unsafe {
129 cvt(ffi::OCSP_check_validity(
130 self.this_update.as_ptr(),
131 self.next_update.as_ptr(),
132 nsec as c_long,
133 maxsec.map(|n| n as c_long).unwrap_or(-1),
134 )).map(|_| ())
135 }
136 }
137 }
138
139 foreign_type_and_impl_send_sync! {
140 type CType = ffi::OCSP_BASICRESP;
141 fn drop = ffi::OCSP_BASICRESP_free;
142
143 pub struct OcspBasicResponse;
144 pub struct OcspBasicResponseRef;
145 }
146
147 impl OcspBasicResponseRef {
148 /// Verifies the validity of the response.
149 ///
150 /// The `certs` parameter contains a set of certificates that will be searched when locating the
151 /// OCSP response signing certificate. Some responders do not include this in the response.
152 pub fn verify(
153 &self,
154 certs: &StackRef<X509>,
155 store: &X509StoreRef,
156 flags: Flag,
157 ) -> Result<(), ErrorStack> {
158 unsafe {
159 cvt(ffi::OCSP_basic_verify(
160 self.as_ptr(),
161 certs.as_ptr(),
162 store.as_ptr(),
163 flags.bits(),
164 )).map(|_| ())
165 }
166 }
167
168 /// Looks up the status for the specified certificate ID.
169 pub fn find_status<'a>(&'a self, id: &OcspCertIdRef) -> Option<Status<'a>> {
170 unsafe {
171 let mut status = ffi::V_OCSP_CERTSTATUS_UNKNOWN;
172 let mut reason = ffi::OCSP_REVOKED_STATUS_NOSTATUS;
173 let mut revocation_time = ptr::null_mut();
174 let mut this_update = ptr::null_mut();
175 let mut next_update = ptr::null_mut();
176
177 let r = ffi::OCSP_resp_find_status(
178 self.as_ptr(),
179 id.as_ptr(),
180 &mut status,
181 &mut reason,
182 &mut revocation_time,
183 &mut this_update,
184 &mut next_update,
185 );
186 if r == 1 {
187 let revocation_time = if revocation_time.is_null() {
188 None
189 } else {
190 Some(Asn1GeneralizedTimeRef::from_ptr(revocation_time))
191 };
192 Some(Status {
193 status: OcspCertStatus(status),
194 reason: OcspRevokedStatus(status),
195 revocation_time: revocation_time,
196 this_update: Asn1GeneralizedTimeRef::from_ptr(this_update),
197 next_update: Asn1GeneralizedTimeRef::from_ptr(next_update),
198 })
199 } else {
200 None
201 }
202 }
203 }
204 }
205
206 foreign_type_and_impl_send_sync! {
207 type CType = ffi::OCSP_CERTID;
208 fn drop = ffi::OCSP_CERTID_free;
209
210 pub struct OcspCertId;
211 pub struct OcspCertIdRef;
212 }
213
214 impl OcspCertId {
215 /// Constructs a certificate ID for certificate `subject`.
216 pub fn from_cert(
217 digest: MessageDigest,
218 subject: &X509Ref,
219 issuer: &X509Ref,
220 ) -> Result<OcspCertId, ErrorStack> {
221 unsafe {
222 cvt_p(ffi::OCSP_cert_to_id(
223 digest.as_ptr(),
224 subject.as_ptr(),
225 issuer.as_ptr(),
226 )).map(OcspCertId)
227 }
228 }
229 }
230
231 foreign_type_and_impl_send_sync! {
232 type CType = ffi::OCSP_RESPONSE;
233 fn drop = ffi::OCSP_RESPONSE_free;
234
235 pub struct OcspResponse;
236 pub struct OcspResponseRef;
237 }
238
239 impl OcspResponse {
240 /// Creates an OCSP response from the status and optional body.
241 ///
242 /// A body should only be provided if `status` is `RESPONSE_STATUS_SUCCESSFUL`.
243 pub fn create(
244 status: OcspResponseStatus,
245 body: Option<&OcspBasicResponseRef>,
246 ) -> Result<OcspResponse, ErrorStack> {
247 unsafe {
248 ffi::init();
249
250 cvt_p(ffi::OCSP_response_create(
251 status.as_raw(),
252 body.map(|r| r.as_ptr()).unwrap_or(ptr::null_mut()),
253 )).map(OcspResponse)
254 }
255 }
256
257 from_der!(OcspResponse, ffi::d2i_OCSP_RESPONSE);
258 }
259
260 impl OcspResponseRef {
261 to_der!(ffi::i2d_OCSP_RESPONSE);
262
263 /// Returns the status of the response.
264 pub fn status(&self) -> OcspResponseStatus {
265 unsafe { OcspResponseStatus(ffi::OCSP_response_status(self.as_ptr())) }
266 }
267
268 /// Returns the basic response.
269 ///
270 /// This will only succeed if `status()` returns `RESPONSE_STATUS_SUCCESSFUL`.
271 pub fn basic(&self) -> Result<OcspBasicResponse, ErrorStack> {
272 unsafe { cvt_p(ffi::OCSP_response_get1_basic(self.as_ptr())).map(OcspBasicResponse) }
273 }
274 }
275
276 foreign_type_and_impl_send_sync! {
277 type CType = ffi::OCSP_REQUEST;
278 fn drop = ffi::OCSP_REQUEST_free;
279
280 pub struct OcspRequest;
281 pub struct OcspRequestRef;
282 }
283
284 impl OcspRequest {
285 pub fn new() -> Result<OcspRequest, ErrorStack> {
286 unsafe {
287 ffi::init();
288
289 cvt_p(ffi::OCSP_REQUEST_new()).map(OcspRequest)
290 }
291 }
292
293 from_der!(OcspRequest, ffi::d2i_OCSP_REQUEST);
294 }
295
296 impl OcspRequestRef {
297 to_der!(ffi::i2d_OCSP_REQUEST);
298
299 pub fn add_id(&mut self, id: OcspCertId) -> Result<&mut OcspOneReqRef, ErrorStack> {
300 unsafe {
301 let ptr = cvt_p(ffi::OCSP_request_add0_id(self.as_ptr(), id.as_ptr()))?;
302 mem::forget(id);
303 Ok(OcspOneReqRef::from_ptr_mut(ptr))
304 }
305 }
306 }
307
308 foreign_type_and_impl_send_sync! {
309 type CType = ffi::OCSP_ONEREQ;
310 fn drop = ffi::OCSP_ONEREQ_free;
311
312 pub struct OcspOneReq;
313 pub struct OcspOneReqRef;
314 }