aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/ssl/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openssl/src/ssl/mod.rs')
-rw-r--r--openssl/src/ssl/mod.rs35
1 files changed, 34 insertions, 1 deletions
diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs
index 058231ca..e06d613b 100644
--- a/openssl/src/ssl/mod.rs
+++ b/openssl/src/ssl/mod.rs
@@ -1,4 +1,4 @@
-use libc::{c_int, c_void, c_long};
+use libc::{c_int, c_void, c_long, c_uint, c_uchar};
use std::ffi::{CStr, CString};
use std::fmt;
use std::io;
@@ -6,6 +6,7 @@ use std::io::prelude::*;
use std::ffi::AsOsStr;
use std::mem;
use std::net;
+use std::slice;
use std::num::FromPrimitive;
use std::num::Int;
use std::path::Path;
@@ -220,6 +221,34 @@ extern fn raw_verify_with_data<T>(preverify_ok: c_int,
}
}
+/// The function is given as the callback to `SSL_CTX_set_next_proto_select_cb`.
+///
+/// It chooses the protocol that the client wishes to use, out of the given list of protocols
+/// supported by the server. It achieves this by delegating to the `SSL_select_next_proto`
+/// function. The list of protocols supported by the client is found in the extra data of the
+/// OpenSSL context.
+#[cfg(feature = "npn")]
+extern fn raw_next_proto_select_cb(ssl: *mut ffi::SSL,
+ out: *mut *mut c_uchar, outlen: *mut c_uchar,
+ inbuf: *const c_uchar, inlen: c_uint,
+ _arg: *mut c_void) -> c_int {
+ unsafe {
+ // First, get the list of protocols (that the client should support) 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());
+ let protocols: &Vec<u8> = mem::transmute(protocols);
+ // Prepare the client list parameters to be passed to the OpenSSL function...
+ let client = protocols.as_ptr();
+ let client_len = protocols.len() as c_uint;
+ // Finally, let OpenSSL find a protocol to be used, by matching the given server and
+ // client lists.
+ ffi::SSL_select_next_proto(out, outlen, inbuf, inlen, client, client_len);
+ }
+
+ 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;
@@ -393,6 +422,10 @@ impl SslContext {
// so that we can refer to it within the callback.
ffi::SSL_CTX_set_ex_data(*self.ctx, get_npn_protos_idx(),
mem::transmute(protocols));
+ // Now register the callback that performs the default protocol
+ // 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());
}
}
}