From be674a28e0791ee652e1397418290d19b263cf42 Mon Sep 17 00:00:00 2001 From: Marko Lalic Date: Wed, 18 Mar 2015 20:52:17 +0100 Subject: [PATCH] openssl: Advertise NPN protocols for server sockets If a server socket is created with a context on which the `set_npn_protocols` method has been called, during TLS connection establishment, the server will advertise the list of protocols given to the method, in case the client indicates that it supports the NPN TLS extension. --- openssl/src/ssl/mod.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index fb5c2440..3aa01d41 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -249,6 +249,36 @@ extern fn raw_next_proto_select_cb(ssl: *mut ffi::SSL, ffi::SSL_TLSEXT_ERR_OK } +/// The function is given as the callback to `SSL_CTX_set_next_protos_advertised_cb`. +/// +/// It causes the parameter `out` to point at a `*const c_uchar` instance that +/// represents the list of protocols that the server should advertise as those +/// that it supports. +/// The list of supported protocols is found in the extra data of the OpenSSL +/// context. +#[cfg(feature = "npn")] +extern fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, + out: *mut *const c_uchar, outlen: *mut c_uint, + _arg: *mut c_void) -> c_int { + unsafe { + // First, get the list of (supported) protocols saved in the context extra data. + let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); + let protocols = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_npn_protos_idx()); + if protocols.is_null() { + *out = b"".as_ptr(); + *outlen = 0; + } else { + // If the pointer is valid, put the pointer to the actual byte array into the + // output parameter `out`, as well as its length into `outlen`. + let protocols: &Vec = mem::transmute(protocols); + *out = protocols.as_ptr(); + *outlen = protocols.len() as c_uint; + } + } + + ffi::SSL_TLSEXT_ERR_OK +} + /// The signature of functions that can be used to manually verify certificates pub type VerifyCallback = fn(preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool; @@ -426,6 +456,9 @@ impl SslContext { // matching based on the client-supported list of protocols that // has been saved. ffi::SSL_CTX_set_next_proto_select_cb(*self.ctx, raw_next_proto_select_cb, ptr::null_mut()); + // Also register the callback to advertise these protocols, if a server socket is + // created with the context. + ffi::SSL_CTX_set_next_protos_advertised_cb(*self.ctx, raw_next_protos_advertise_cb, ptr::null_mut()); } } }