impl ExtensionTracker { // Technically the as_mut() call here is the only unsafe bit, // but don't call this function lightly. unsafefn wrap_handler_call<F, T>(arg: *mut c_void, f: F) -> T where
F: FnOnce(&mutdyn ExtensionHandler) -> T,
{ let rc = arg.cast::<BoxedExtensionHandler>().as_mut().unwrap();
f(&mut *rc.borrow_mut())
}
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] unsafeextern"C"fn extension_writer(
_fd: *mut PRFileDesc,
message: SSLHandshakeType::Type,
data: *mut u8,
len: *mut c_uint,
max_len: c_uint,
arg: *mut c_void,
) -> PRBool { let d = std::slice::from_raw_parts_mut(data, max_len as usize); Self::wrap_handler_call(arg, |handler| { // Cast is safe here because the message type is always part of the enum match handler.write(message as HandshakeMessage, d) {
ExtensionWriterResult::Write(sz) => {
*len = c_uint::try_from(sz).expect("integer overflow from extension writer"); 1
}
ExtensionWriterResult::Skip => 0,
}
})
}
unsafeextern"C"fn extension_handler(
_fd: *mut PRFileDesc,
message: SSLHandshakeType::Type,
data: *const u8,
len: c_uint,
alert: *mut SSLAlertDescription,
arg: *mut c_void,
) -> SECStatus { let d = null_safe_slice(data, len); #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] Self::wrap_handler_call(arg, |handler| { // Cast is safe here because the message type is always part of the enum match handler.handle(message as HandshakeMessage, d) {
ExtensionHandlerResult::Ok => SECSuccess,
ExtensionHandlerResult::Alert(a) => {
*alert = a;
SECFailure
}
}
})
}
/// Use the provided handler to manage an extension. This is quite unsafe. /// /// # Safety /// /// The holder of this `ExtensionTracker` needs to ensure that it lives at /// least as long as the file descriptor, as NSS provides no way to remove /// an extension handler once it is configured. /// /// # Errors /// /// If the underlying NSS API fails to register a handler. pubunsafefn new(
fd: *mut PRFileDesc,
extension: Extension,
handler: Rc<RefCell<dyn ExtensionHandler>>,
) -> Res<Self> { // The ergonomics here aren't great for users of this API, but it's // horrific here. The pinned outer box gives us a stable pointer to the inner // box. This is the pointer that is passed to NSS. // // The inner box points to the reference-counted object. This inner box is // what we end up with a reference to in callbacks. That extra wrapper around // the Rc avoid any touching of reference counts in callbacks, which would // inevitably lead to leaks as we don't control how many times the callback // is invoked. // // This way, only this "outer" code deals with the reference count. letmut tracker = Self {
extension,
handler: Box::pin(Box::new(handler)),
};
SSL_InstallExtensionHooks(
fd,
extension,
Some(Self::extension_writer),
as_c_void(&mut tracker.handler),
Some(Self::extension_handler),
as_c_void(&mut tracker.handler),
)?;
Ok(tracker)
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.