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