/rust/registry/src/index.crates.io-1949cf8c6b5b557f/openssl-0.10.62/src/ssl/callbacks.rs
Line | Count | Source |
1 | | use cfg_if::cfg_if; |
2 | | use foreign_types::ForeignType; |
3 | | use foreign_types::ForeignTypeRef; |
4 | | #[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))] |
5 | | use libc::c_char; |
6 | | #[cfg(ossl111)] |
7 | | use libc::size_t; |
8 | | use libc::{c_int, c_uchar, c_uint, c_void}; |
9 | | #[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))] |
10 | | use std::ffi::CStr; |
11 | | use std::mem; |
12 | | use std::ptr; |
13 | | use std::slice; |
14 | | #[cfg(ossl111)] |
15 | | use std::str; |
16 | | use std::sync::Arc; |
17 | | |
18 | | use crate::dh::Dh; |
19 | | #[cfg(all(ossl101, not(ossl110)))] |
20 | | use crate::ec::EcKey; |
21 | | use crate::error::ErrorStack; |
22 | | use crate::pkey::Params; |
23 | | #[cfg(any(ossl102, libressl261))] |
24 | | use crate::ssl::AlpnError; |
25 | | use crate::ssl::{ |
26 | | try_get_session_ctx_index, SniError, Ssl, SslAlert, SslContext, SslContextRef, SslRef, |
27 | | SslSession, SslSessionRef, |
28 | | }; |
29 | | #[cfg(ossl111)] |
30 | | use crate::ssl::{ClientHelloResponse, ExtensionContext}; |
31 | | #[cfg(ossl111)] |
32 | | use crate::util::ForeignTypeRefExt; |
33 | | #[cfg(ossl111)] |
34 | | use crate::x509::X509Ref; |
35 | | use crate::x509::{X509StoreContext, X509StoreContextRef}; |
36 | | |
37 | 0 | pub extern "C" fn raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int |
38 | 0 | where |
39 | 0 | F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, |
40 | | { |
41 | | unsafe { |
42 | 0 | let ctx = X509StoreContextRef::from_ptr_mut(x509_ctx); |
43 | 0 | let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing"); |
44 | 0 | let verify_idx = SslContext::cached_ex_index::<F>(); |
45 | | |
46 | | // raw pointer shenanigans to break the borrow of ctx |
47 | | // the callback can't mess with its own ex_data slot so this is safe |
48 | 0 | let verify = ctx |
49 | 0 | .ex_data(ssl_idx) |
50 | 0 | .expect("BUG: store context missing ssl") |
51 | 0 | .ssl_context() |
52 | 0 | .ex_data(verify_idx) |
53 | 0 | .expect("BUG: verify callback missing") as *const F; |
54 | | |
55 | 0 | (*verify)(preverify_ok != 0, ctx) as c_int |
56 | | } |
57 | 0 | } |
58 | | |
59 | | #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] |
60 | 0 | pub extern "C" fn raw_client_psk<F>( |
61 | 0 | ssl: *mut ffi::SSL, |
62 | 0 | hint: *const c_char, |
63 | 0 | identity: *mut c_char, |
64 | 0 | max_identity_len: c_uint, |
65 | 0 | psk: *mut c_uchar, |
66 | 0 | max_psk_len: c_uint, |
67 | 0 | ) -> c_uint |
68 | 0 | where |
69 | 0 | F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> |
70 | 0 | + 'static |
71 | 0 | + Sync |
72 | 0 | + Send, |
73 | | { |
74 | | unsafe { |
75 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
76 | 0 | let callback_idx = SslContext::cached_ex_index::<F>(); |
77 | | |
78 | 0 | let callback = ssl |
79 | 0 | .ssl_context() |
80 | 0 | .ex_data(callback_idx) |
81 | 0 | .expect("BUG: psk callback missing") as *const F; |
82 | 0 | let hint = if !hint.is_null() { |
83 | 0 | Some(CStr::from_ptr(hint).to_bytes()) |
84 | | } else { |
85 | 0 | None |
86 | | }; |
87 | | // Give the callback mutable slices into which it can write the identity and psk. |
88 | 0 | let identity_sl = slice::from_raw_parts_mut(identity as *mut u8, max_identity_len as usize); |
89 | | #[allow(clippy::unnecessary_cast)] |
90 | 0 | let psk_sl = slice::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize); |
91 | 0 | match (*callback)(ssl, hint, identity_sl, psk_sl) { |
92 | 0 | Ok(psk_len) => psk_len as u32, |
93 | 0 | Err(e) => { |
94 | 0 | e.put(); |
95 | 0 | 0 |
96 | | } |
97 | | } |
98 | | } |
99 | 0 | } |
100 | | |
101 | | #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] |
102 | 0 | pub extern "C" fn raw_server_psk<F>( |
103 | 0 | ssl: *mut ffi::SSL, |
104 | 0 | identity: *const c_char, |
105 | 0 | psk: *mut c_uchar, |
106 | 0 | max_psk_len: c_uint, |
107 | 0 | ) -> c_uint |
108 | 0 | where |
109 | 0 | F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack> |
110 | 0 | + 'static |
111 | 0 | + Sync |
112 | 0 | + Send, |
113 | | { |
114 | | unsafe { |
115 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
116 | 0 | let callback_idx = SslContext::cached_ex_index::<F>(); |
117 | | |
118 | 0 | let callback = ssl |
119 | 0 | .ssl_context() |
120 | 0 | .ex_data(callback_idx) |
121 | 0 | .expect("BUG: psk callback missing") as *const F; |
122 | 0 | let identity = if identity.is_null() { |
123 | 0 | None |
124 | | } else { |
125 | 0 | Some(CStr::from_ptr(identity).to_bytes()) |
126 | | }; |
127 | | // Give the callback mutable slices into which it can write the psk. |
128 | | #[allow(clippy::unnecessary_cast)] |
129 | 0 | let psk_sl = slice::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize); |
130 | 0 | match (*callback)(ssl, identity, psk_sl) { |
131 | 0 | Ok(psk_len) => psk_len as u32, |
132 | 0 | Err(e) => { |
133 | 0 | e.put(); |
134 | 0 | 0 |
135 | | } |
136 | | } |
137 | | } |
138 | 0 | } |
139 | | |
140 | 0 | pub extern "C" fn ssl_raw_verify<F>( |
141 | 0 | preverify_ok: c_int, |
142 | 0 | x509_ctx: *mut ffi::X509_STORE_CTX, |
143 | 0 | ) -> c_int |
144 | 0 | where |
145 | 0 | F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, |
146 | | { |
147 | | unsafe { |
148 | 0 | let ctx = X509StoreContextRef::from_ptr_mut(x509_ctx); |
149 | 0 | let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing"); |
150 | 0 | let callback_idx = Ssl::cached_ex_index::<Arc<F>>(); |
151 | | |
152 | 0 | let callback = ctx |
153 | 0 | .ex_data(ssl_idx) |
154 | 0 | .expect("BUG: store context missing ssl") |
155 | 0 | .ex_data(callback_idx) |
156 | 0 | .expect("BUG: ssl verify callback missing") |
157 | 0 | .clone(); |
158 | | |
159 | 0 | callback(preverify_ok != 0, ctx) as c_int |
160 | | } |
161 | 0 | } |
162 | | |
163 | 0 | pub extern "C" fn raw_sni<F>(ssl: *mut ffi::SSL, al: *mut c_int, arg: *mut c_void) -> c_int |
164 | 0 | where |
165 | 0 | F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send, |
166 | | { |
167 | | unsafe { |
168 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
169 | 0 | let callback = arg as *const F; |
170 | 0 | let mut alert = SslAlert(*al); |
171 | | |
172 | 0 | let r = (*callback)(ssl, &mut alert); |
173 | 0 | *al = alert.0; |
174 | 0 | match r { |
175 | 0 | Ok(()) => ffi::SSL_TLSEXT_ERR_OK, |
176 | 0 | Err(e) => e.0, |
177 | | } |
178 | | } |
179 | 0 | } |
180 | | |
181 | | #[cfg(any(ossl102, libressl261))] |
182 | 0 | pub extern "C" fn raw_alpn_select<F>( |
183 | 0 | ssl: *mut ffi::SSL, |
184 | 0 | out: *mut *const c_uchar, |
185 | 0 | outlen: *mut c_uchar, |
186 | 0 | inbuf: *const c_uchar, |
187 | 0 | inlen: c_uint, |
188 | 0 | _arg: *mut c_void, |
189 | 0 | ) -> c_int |
190 | 0 | where |
191 | 0 | F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send, |
192 | | { |
193 | | unsafe { |
194 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
195 | 0 | let callback = ssl |
196 | 0 | .ssl_context() |
197 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
198 | 0 | .expect("BUG: alpn callback missing") as *const F; |
199 | | #[allow(clippy::unnecessary_cast)] |
200 | 0 | let protos = slice::from_raw_parts(inbuf as *const u8, inlen as usize); |
201 | | |
202 | 0 | match (*callback)(ssl, protos) { |
203 | 0 | Ok(proto) => { |
204 | 0 | *out = proto.as_ptr() as *const c_uchar; |
205 | 0 | *outlen = proto.len() as c_uchar; |
206 | 0 | ffi::SSL_TLSEXT_ERR_OK |
207 | | } |
208 | 0 | Err(e) => e.0, |
209 | | } |
210 | | } |
211 | 0 | } |
212 | | |
213 | 0 | pub unsafe extern "C" fn raw_tmp_dh<F>( |
214 | 0 | ssl: *mut ffi::SSL, |
215 | 0 | is_export: c_int, |
216 | 0 | keylength: c_int, |
217 | 0 | ) -> *mut ffi::DH |
218 | 0 | where |
219 | 0 | F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, |
220 | | { |
221 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
222 | 0 | let callback = ssl |
223 | 0 | .ssl_context() |
224 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
225 | 0 | .expect("BUG: tmp dh callback missing") as *const F; |
226 | | |
227 | 0 | match (*callback)(ssl, is_export != 0, keylength as u32) { |
228 | 0 | Ok(dh) => { |
229 | 0 | let ptr = dh.as_ptr(); |
230 | 0 | mem::forget(dh); |
231 | 0 | ptr |
232 | | } |
233 | 0 | Err(e) => { |
234 | 0 | e.put(); |
235 | 0 | ptr::null_mut() |
236 | | } |
237 | | } |
238 | 0 | } |
239 | | |
240 | | #[cfg(all(ossl101, not(ossl110)))] |
241 | | pub unsafe extern "C" fn raw_tmp_ecdh<F>( |
242 | | ssl: *mut ffi::SSL, |
243 | | is_export: c_int, |
244 | | keylength: c_int, |
245 | | ) -> *mut ffi::EC_KEY |
246 | | where |
247 | | F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, |
248 | | { |
249 | | let ssl = SslRef::from_ptr_mut(ssl); |
250 | | let callback = ssl |
251 | | .ssl_context() |
252 | | .ex_data(SslContext::cached_ex_index::<F>()) |
253 | | .expect("BUG: tmp ecdh callback missing") as *const F; |
254 | | |
255 | | match (*callback)(ssl, is_export != 0, keylength as u32) { |
256 | | Ok(ec_key) => { |
257 | | let ptr = ec_key.as_ptr(); |
258 | | mem::forget(ec_key); |
259 | | ptr |
260 | | } |
261 | | Err(e) => { |
262 | | e.put(); |
263 | | ptr::null_mut() |
264 | | } |
265 | | } |
266 | | } |
267 | | |
268 | 0 | pub unsafe extern "C" fn raw_tmp_dh_ssl<F>( |
269 | 0 | ssl: *mut ffi::SSL, |
270 | 0 | is_export: c_int, |
271 | 0 | keylength: c_int, |
272 | 0 | ) -> *mut ffi::DH |
273 | 0 | where |
274 | 0 | F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, |
275 | | { |
276 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
277 | 0 | let callback = ssl |
278 | 0 | .ex_data(Ssl::cached_ex_index::<Arc<F>>()) |
279 | 0 | .expect("BUG: ssl tmp dh callback missing") |
280 | 0 | .clone(); |
281 | | |
282 | 0 | match callback(ssl, is_export != 0, keylength as u32) { |
283 | 0 | Ok(dh) => { |
284 | 0 | let ptr = dh.as_ptr(); |
285 | 0 | mem::forget(dh); |
286 | 0 | ptr |
287 | | } |
288 | 0 | Err(e) => { |
289 | 0 | e.put(); |
290 | 0 | ptr::null_mut() |
291 | | } |
292 | | } |
293 | 0 | } |
294 | | |
295 | | #[cfg(all(ossl101, not(ossl110)))] |
296 | | pub unsafe extern "C" fn raw_tmp_ecdh_ssl<F>( |
297 | | ssl: *mut ffi::SSL, |
298 | | is_export: c_int, |
299 | | keylength: c_int, |
300 | | ) -> *mut ffi::EC_KEY |
301 | | where |
302 | | F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, |
303 | | { |
304 | | let ssl = SslRef::from_ptr_mut(ssl); |
305 | | let callback = ssl |
306 | | .ex_data(Ssl::cached_ex_index::<Arc<F>>()) |
307 | | .expect("BUG: ssl tmp ecdh callback missing") |
308 | | .clone(); |
309 | | |
310 | | match callback(ssl, is_export != 0, keylength as u32) { |
311 | | Ok(ec_key) => { |
312 | | let ptr = ec_key.as_ptr(); |
313 | | mem::forget(ec_key); |
314 | | ptr |
315 | | } |
316 | | Err(e) => { |
317 | | e.put(); |
318 | | ptr::null_mut() |
319 | | } |
320 | | } |
321 | | } |
322 | | |
323 | 0 | pub unsafe extern "C" fn raw_tlsext_status<F>(ssl: *mut ffi::SSL, _: *mut c_void) -> c_int |
324 | 0 | where |
325 | 0 | F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send, |
326 | | { |
327 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
328 | 0 | let callback = ssl |
329 | 0 | .ssl_context() |
330 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
331 | 0 | .expect("BUG: ocsp callback missing") as *const F; |
332 | 0 | let ret = (*callback)(ssl); |
333 | | |
334 | 0 | if ssl.is_server() { |
335 | 0 | match ret { |
336 | 0 | Ok(true) => ffi::SSL_TLSEXT_ERR_OK, |
337 | 0 | Ok(false) => ffi::SSL_TLSEXT_ERR_NOACK, |
338 | 0 | Err(e) => { |
339 | 0 | e.put(); |
340 | 0 | ffi::SSL_TLSEXT_ERR_ALERT_FATAL |
341 | | } |
342 | | } |
343 | | } else { |
344 | 0 | match ret { |
345 | 0 | Ok(true) => 1, |
346 | 0 | Ok(false) => 0, |
347 | 0 | Err(e) => { |
348 | 0 | e.put(); |
349 | 0 | -1 |
350 | | } |
351 | | } |
352 | | } |
353 | 0 | } |
354 | | |
355 | 0 | pub unsafe extern "C" fn raw_new_session<F>( |
356 | 0 | ssl: *mut ffi::SSL, |
357 | 0 | session: *mut ffi::SSL_SESSION, |
358 | 0 | ) -> c_int |
359 | 0 | where |
360 | 0 | F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send, |
361 | | { |
362 | 0 | let session_ctx_index = |
363 | 0 | try_get_session_ctx_index().expect("BUG: session context index initialization failed"); |
364 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
365 | 0 | let callback = ssl |
366 | 0 | .ex_data(*session_ctx_index) |
367 | 0 | .expect("BUG: session context missing") |
368 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
369 | 0 | .expect("BUG: new session callback missing") as *const F; |
370 | 0 | let session = SslSession::from_ptr(session); |
371 | | |
372 | 0 | (*callback)(ssl, session); |
373 | | |
374 | | // the return code doesn't indicate error vs success, but whether or not we consumed the session |
375 | 0 | 1 |
376 | 0 | } |
377 | | |
378 | 0 | pub unsafe extern "C" fn raw_remove_session<F>( |
379 | 0 | ctx: *mut ffi::SSL_CTX, |
380 | 0 | session: *mut ffi::SSL_SESSION, |
381 | 0 | ) where |
382 | 0 | F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send, |
383 | | { |
384 | 0 | let ctx = SslContextRef::from_ptr(ctx); |
385 | 0 | let callback = ctx |
386 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
387 | 0 | .expect("BUG: remove session callback missing"); |
388 | 0 | let session = SslSessionRef::from_ptr(session); |
389 | | |
390 | 0 | callback(ctx, session) |
391 | 0 | } |
392 | | |
393 | | cfg_if! { |
394 | | if #[cfg(any(ossl110, libressl280, boringssl))] { |
395 | | type DataPtr = *const c_uchar; |
396 | | } else { |
397 | | type DataPtr = *mut c_uchar; |
398 | | } |
399 | | } |
400 | | |
401 | 0 | pub unsafe extern "C" fn raw_get_session<F>( |
402 | 0 | ssl: *mut ffi::SSL, |
403 | 0 | data: DataPtr, |
404 | 0 | len: c_int, |
405 | 0 | copy: *mut c_int, |
406 | 0 | ) -> *mut ffi::SSL_SESSION |
407 | 0 | where |
408 | 0 | F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send, |
409 | | { |
410 | 0 | let session_ctx_index = |
411 | 0 | try_get_session_ctx_index().expect("BUG: session context index initialization failed"); |
412 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
413 | 0 | let callback = ssl |
414 | 0 | .ex_data(*session_ctx_index) |
415 | 0 | .expect("BUG: session context missing") |
416 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
417 | 0 | .expect("BUG: get session callback missing") as *const F; |
418 | | #[allow(clippy::unnecessary_cast)] |
419 | 0 | let data = slice::from_raw_parts(data as *const u8, len as usize); |
420 | | |
421 | 0 | match (*callback)(ssl, data) { |
422 | 0 | Some(session) => { |
423 | 0 | let p = session.as_ptr(); |
424 | 0 | mem::forget(session); |
425 | 0 | *copy = 0; |
426 | 0 | p |
427 | | } |
428 | 0 | None => ptr::null_mut(), |
429 | | } |
430 | 0 | } |
431 | | |
432 | | #[cfg(ossl111)] |
433 | 0 | pub unsafe extern "C" fn raw_keylog<F>(ssl: *const ffi::SSL, line: *const c_char) |
434 | 0 | where |
435 | 0 | F: Fn(&SslRef, &str) + 'static + Sync + Send, |
436 | | { |
437 | 0 | let ssl = SslRef::from_const_ptr(ssl); |
438 | 0 | let callback = ssl |
439 | 0 | .ssl_context() |
440 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
441 | 0 | .expect("BUG: get session callback missing"); |
442 | 0 | let line = CStr::from_ptr(line).to_bytes(); |
443 | 0 | let line = str::from_utf8_unchecked(line); |
444 | | |
445 | 0 | callback(ssl, line); |
446 | 0 | } |
447 | | |
448 | | #[cfg(ossl111)] |
449 | 0 | pub unsafe extern "C" fn raw_stateless_cookie_generate<F>( |
450 | 0 | ssl: *mut ffi::SSL, |
451 | 0 | cookie: *mut c_uchar, |
452 | 0 | cookie_len: *mut size_t, |
453 | 0 | ) -> c_int |
454 | 0 | where |
455 | 0 | F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, |
456 | | { |
457 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
458 | 0 | let callback = ssl |
459 | 0 | .ssl_context() |
460 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
461 | 0 | .expect("BUG: stateless cookie generate callback missing") as *const F; |
462 | | #[allow(clippy::unnecessary_cast)] |
463 | 0 | let slice = slice::from_raw_parts_mut(cookie as *mut u8, ffi::SSL_COOKIE_LENGTH as usize); |
464 | 0 | match (*callback)(ssl, slice) { |
465 | 0 | Ok(len) => { |
466 | 0 | *cookie_len = len as size_t; |
467 | 0 | 1 |
468 | | } |
469 | 0 | Err(e) => { |
470 | 0 | e.put(); |
471 | 0 | 0 |
472 | | } |
473 | | } |
474 | 0 | } |
475 | | |
476 | | #[cfg(ossl111)] |
477 | 0 | pub unsafe extern "C" fn raw_stateless_cookie_verify<F>( |
478 | 0 | ssl: *mut ffi::SSL, |
479 | 0 | cookie: *const c_uchar, |
480 | 0 | cookie_len: size_t, |
481 | 0 | ) -> c_int |
482 | 0 | where |
483 | 0 | F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, |
484 | | { |
485 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
486 | 0 | let callback = ssl |
487 | 0 | .ssl_context() |
488 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
489 | 0 | .expect("BUG: stateless cookie verify callback missing") as *const F; |
490 | | #[allow(clippy::unnecessary_cast)] |
491 | 0 | let slice = slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len); |
492 | 0 | (*callback)(ssl, slice) as c_int |
493 | 0 | } |
494 | | |
495 | | #[cfg(not(boringssl))] |
496 | 0 | pub extern "C" fn raw_cookie_generate<F>( |
497 | 0 | ssl: *mut ffi::SSL, |
498 | 0 | cookie: *mut c_uchar, |
499 | 0 | cookie_len: *mut c_uint, |
500 | 0 | ) -> c_int |
501 | 0 | where |
502 | 0 | F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, |
503 | | { |
504 | | unsafe { |
505 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
506 | 0 | let callback = ssl |
507 | 0 | .ssl_context() |
508 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
509 | 0 | .expect("BUG: cookie generate callback missing") as *const F; |
510 | | // We subtract 1 from DTLS1_COOKIE_LENGTH as the ostensible value, 256, is erroneous but retained for |
511 | | // compatibility. See comments in dtls1.h. |
512 | | #[allow(clippy::unnecessary_cast)] |
513 | 0 | let slice = |
514 | 0 | slice::from_raw_parts_mut(cookie as *mut u8, ffi::DTLS1_COOKIE_LENGTH as usize - 1); |
515 | 0 | match (*callback)(ssl, slice) { |
516 | 0 | Ok(len) => { |
517 | 0 | *cookie_len = len as c_uint; |
518 | 0 | 1 |
519 | | } |
520 | 0 | Err(e) => { |
521 | 0 | e.put(); |
522 | 0 | 0 |
523 | | } |
524 | | } |
525 | | } |
526 | 0 | } |
527 | | |
528 | | #[cfg(not(boringssl))] |
529 | | cfg_if! { |
530 | | if #[cfg(any(ossl110, libressl280))] { |
531 | | type CookiePtr = *const c_uchar; |
532 | | } else { |
533 | | type CookiePtr = *mut c_uchar; |
534 | | } |
535 | | } |
536 | | |
537 | | #[cfg(not(boringssl))] |
538 | 0 | pub extern "C" fn raw_cookie_verify<F>( |
539 | 0 | ssl: *mut ffi::SSL, |
540 | 0 | cookie: CookiePtr, |
541 | 0 | cookie_len: c_uint, |
542 | 0 | ) -> c_int |
543 | 0 | where |
544 | 0 | F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, |
545 | | { |
546 | | unsafe { |
547 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
548 | 0 | let callback = ssl |
549 | 0 | .ssl_context() |
550 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
551 | 0 | .expect("BUG: cookie verify callback missing") as *const F; |
552 | | #[allow(clippy::unnecessary_cast)] |
553 | 0 | let slice = |
554 | 0 | slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize); |
555 | 0 | (*callback)(ssl, slice) as c_int |
556 | | } |
557 | 0 | } |
558 | | |
559 | | #[cfg(ossl111)] |
560 | | pub struct CustomExtAddState<T>(Option<T>); |
561 | | |
562 | | #[cfg(ossl111)] |
563 | 0 | pub extern "C" fn raw_custom_ext_add<F, T>( |
564 | 0 | ssl: *mut ffi::SSL, |
565 | 0 | _: c_uint, |
566 | 0 | context: c_uint, |
567 | 0 | out: *mut *const c_uchar, |
568 | 0 | outlen: *mut size_t, |
569 | 0 | x: *mut ffi::X509, |
570 | 0 | chainidx: size_t, |
571 | 0 | al: *mut c_int, |
572 | 0 | _: *mut c_void, |
573 | 0 | ) -> c_int |
574 | 0 | where |
575 | 0 | F: Fn(&mut SslRef, ExtensionContext, Option<(usize, &X509Ref)>) -> Result<Option<T>, SslAlert> |
576 | 0 | + 'static |
577 | 0 | + Sync |
578 | 0 | + Send, |
579 | 0 | T: AsRef<[u8]> + 'static + Sync + Send, |
580 | | { |
581 | | unsafe { |
582 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
583 | 0 | let callback = ssl |
584 | 0 | .ssl_context() |
585 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
586 | 0 | .expect("BUG: custom ext add callback missing") as *const F; |
587 | 0 | let ectx = ExtensionContext::from_bits_truncate(context); |
588 | 0 | let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) { |
589 | 0 | Some((chainidx, X509Ref::from_ptr(x))) |
590 | | } else { |
591 | 0 | None |
592 | | }; |
593 | 0 | match (*callback)(ssl, ectx, cert) { |
594 | 0 | Ok(None) => 0, |
595 | 0 | Ok(Some(buf)) => { |
596 | 0 | *outlen = buf.as_ref().len(); |
597 | 0 | *out = buf.as_ref().as_ptr(); |
598 | | |
599 | 0 | let idx = Ssl::cached_ex_index::<CustomExtAddState<T>>(); |
600 | 0 | let mut buf = Some(buf); |
601 | 0 | let new = match ssl.ex_data_mut(idx) { |
602 | 0 | Some(state) => { |
603 | 0 | state.0 = buf.take(); |
604 | 0 | false |
605 | | } |
606 | 0 | None => true, |
607 | | }; |
608 | 0 | if new { |
609 | 0 | ssl.set_ex_data(idx, CustomExtAddState(buf)); |
610 | 0 | } |
611 | 0 | 1 |
612 | | } |
613 | 0 | Err(alert) => { |
614 | 0 | *al = alert.0; |
615 | 0 | -1 |
616 | | } |
617 | | } |
618 | | } |
619 | 0 | } |
620 | | |
621 | | #[cfg(ossl111)] |
622 | 0 | pub extern "C" fn raw_custom_ext_free<T>( |
623 | 0 | ssl: *mut ffi::SSL, |
624 | 0 | _: c_uint, |
625 | 0 | _: c_uint, |
626 | 0 | _: *const c_uchar, |
627 | 0 | _: *mut c_void, |
628 | 0 | ) where |
629 | 0 | T: 'static + Sync + Send, |
630 | | { |
631 | | unsafe { |
632 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
633 | 0 | let idx = Ssl::cached_ex_index::<CustomExtAddState<T>>(); |
634 | 0 | if let Some(state) = ssl.ex_data_mut(idx) { |
635 | 0 | state.0 = None; |
636 | 0 | } |
637 | | } |
638 | 0 | } |
639 | | |
640 | | #[cfg(ossl111)] |
641 | 0 | pub extern "C" fn raw_custom_ext_parse<F>( |
642 | 0 | ssl: *mut ffi::SSL, |
643 | 0 | _: c_uint, |
644 | 0 | context: c_uint, |
645 | 0 | input: *const c_uchar, |
646 | 0 | inlen: size_t, |
647 | 0 | x: *mut ffi::X509, |
648 | 0 | chainidx: size_t, |
649 | 0 | al: *mut c_int, |
650 | 0 | _: *mut c_void, |
651 | 0 | ) -> c_int |
652 | 0 | where |
653 | 0 | F: Fn(&mut SslRef, ExtensionContext, &[u8], Option<(usize, &X509Ref)>) -> Result<(), SslAlert> |
654 | 0 | + 'static |
655 | 0 | + Sync |
656 | 0 | + Send, |
657 | | { |
658 | | unsafe { |
659 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
660 | 0 | let callback = ssl |
661 | 0 | .ssl_context() |
662 | 0 | .ex_data(SslContext::cached_ex_index::<F>()) |
663 | 0 | .expect("BUG: custom ext parse callback missing") as *const F; |
664 | 0 | let ectx = ExtensionContext::from_bits_truncate(context); |
665 | | #[allow(clippy::unnecessary_cast)] |
666 | 0 | let slice = slice::from_raw_parts(input as *const u8, inlen); |
667 | 0 | let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) { |
668 | 0 | Some((chainidx, X509Ref::from_ptr(x))) |
669 | | } else { |
670 | 0 | None |
671 | | }; |
672 | 0 | match (*callback)(ssl, ectx, slice, cert) { |
673 | 0 | Ok(()) => 1, |
674 | 0 | Err(alert) => { |
675 | 0 | *al = alert.0; |
676 | 0 | 0 |
677 | | } |
678 | | } |
679 | | } |
680 | 0 | } |
681 | | |
682 | | #[cfg(ossl111)] |
683 | 0 | pub unsafe extern "C" fn raw_client_hello<F>( |
684 | 0 | ssl: *mut ffi::SSL, |
685 | 0 | al: *mut c_int, |
686 | 0 | arg: *mut c_void, |
687 | 0 | ) -> c_int |
688 | 0 | where |
689 | 0 | F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack> |
690 | 0 | + 'static |
691 | 0 | + Sync |
692 | 0 | + Send, |
693 | | { |
694 | 0 | let ssl = SslRef::from_ptr_mut(ssl); |
695 | 0 | let callback = arg as *const F; |
696 | 0 | let mut alert = SslAlert(*al); |
697 | | |
698 | 0 | let r = (*callback)(ssl, &mut alert); |
699 | 0 | *al = alert.0; |
700 | 0 | match r { |
701 | 0 | Ok(c) => c.0, |
702 | 0 | Err(e) => { |
703 | 0 | e.put(); |
704 | 0 | ffi::SSL_CLIENT_HELLO_ERROR |
705 | | } |
706 | | } |
707 | 0 | } |