Merge pull request #39 from andrew-d/andrew-support-tls-sni
Allow setting hostname to support TLS-SNI
This commit is contained in:
commit
0a18409cdb
|
|
@ -39,6 +39,10 @@ pub static SSL_ERROR_WANT_ACCEPT: c_int = 8;
|
||||||
pub static SSL_VERIFY_NONE: c_int = 0;
|
pub static SSL_VERIFY_NONE: c_int = 0;
|
||||||
pub static SSL_VERIFY_PEER: c_int = 1;
|
pub static SSL_VERIFY_PEER: c_int = 1;
|
||||||
|
|
||||||
|
pub static SSL_CTRL_SET_TLSEXT_HOSTNAME: c_int = 55;
|
||||||
|
|
||||||
|
pub static TLSEXT_NAMETYPE_host_name: c_long = 0;
|
||||||
|
|
||||||
pub static X509_V_OK: c_int = 0;
|
pub static X509_V_OK: c_int = 0;
|
||||||
pub static X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: c_int = 2;
|
pub static X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: c_int = 2;
|
||||||
pub static X509_V_ERR_UNABLE_TO_GET_CRL: c_int = 3;
|
pub static X509_V_ERR_UNABLE_TO_GET_CRL: c_int = 3;
|
||||||
|
|
@ -141,6 +145,8 @@ extern "C" {
|
||||||
pub fn SSL_get_rbio(ssl: *mut SSL) -> *mut BIO;
|
pub fn SSL_get_rbio(ssl: *mut SSL) -> *mut BIO;
|
||||||
pub fn SSL_get_wbio(ssl: *mut SSL) -> *mut BIO;
|
pub fn SSL_get_wbio(ssl: *mut SSL) -> *mut BIO;
|
||||||
pub fn SSL_connect(ssl: *mut SSL) -> c_int;
|
pub fn SSL_connect(ssl: *mut SSL) -> c_int;
|
||||||
|
pub fn SSL_ctrl(ssl: *mut SSL, cmd: c_int, larg: c_long,
|
||||||
|
parg: *mut c_void) -> c_long;
|
||||||
pub fn SSL_get_error(ssl: *mut SSL, ret: c_int) -> c_int;
|
pub fn SSL_get_error(ssl: *mut SSL, ret: c_int) -> c_int;
|
||||||
pub fn SSL_read(ssl: *mut SSL, buf: *mut c_void, num: c_int) -> c_int;
|
pub fn SSL_read(ssl: *mut SSL, buf: *mut c_void, num: c_int) -> c_int;
|
||||||
pub fn SSL_write(ssl: *mut SSL, buf: *const c_void, num: c_int) -> c_int;
|
pub fn SSL_write(ssl: *mut SSL, buf: *const c_void, num: c_int) -> c_int;
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,7 @@ make_validation_error!(X509_V_OK,
|
||||||
X509ApplicationVerification = X509_V_ERR_APPLICATION_VERIFICATION,
|
X509ApplicationVerification = X509_V_ERR_APPLICATION_VERIFICATION,
|
||||||
)
|
)
|
||||||
|
|
||||||
struct Ssl {
|
pub struct Ssl {
|
||||||
ssl: *mut ffi::SSL
|
ssl: *mut ffi::SSL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -302,7 +302,7 @@ impl Drop for Ssl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ssl {
|
impl Ssl {
|
||||||
fn try_new(ctx: &SslContext) -> Result<Ssl, SslError> {
|
pub fn try_new(ctx: &SslContext) -> Result<Ssl, SslError> {
|
||||||
let ssl = unsafe { ffi::SSL_new(ctx.ctx) };
|
let ssl = unsafe { ffi::SSL_new(ctx.ctx) };
|
||||||
if ssl == ptr::mut_null() {
|
if ssl == ptr::mut_null() {
|
||||||
return Err(SslError::get());
|
return Err(SslError::get());
|
||||||
|
|
@ -364,6 +364,29 @@ impl Ssl {
|
||||||
None => unreachable!()
|
None => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the host name to be used with SNI (Server Name Indication).
|
||||||
|
pub fn set_hostname(&self, hostname: &str) -> Result<(), SslError> {
|
||||||
|
let ret = hostname.with_c_str(|hostname| {
|
||||||
|
unsafe {
|
||||||
|
// This is defined as a macro:
|
||||||
|
// #define SSL_set_tlsext_host_name(s,name) \
|
||||||
|
// SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)
|
||||||
|
|
||||||
|
ffi::SSL_ctrl(self.ssl, ffi::SSL_CTRL_SET_TLSEXT_HOSTNAME,
|
||||||
|
ffi::TLSEXT_NAMETYPE_host_name,
|
||||||
|
hostname as *const c_void as *mut c_void)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// For this case, 0 indicates failure.
|
||||||
|
if ret == 0 {
|
||||||
|
Err(SslError::get())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(FromPrimitive)]
|
#[deriving(FromPrimitive)]
|
||||||
|
|
@ -442,14 +465,8 @@ pub struct SslStream<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Stream> SslStream<S> {
|
impl<S: Stream> SslStream<S> {
|
||||||
/// Attempts to create a new SSL stream
|
/// Attempts to create a new SSL stream from a given `Ssl` instance.
|
||||||
pub fn try_new(ctx: &SslContext, stream: S) -> Result<SslStream<S>,
|
pub fn new_from(ssl: Ssl, stream: S) -> Result<SslStream<S>, SslError> {
|
||||||
SslError> {
|
|
||||||
let ssl = match Ssl::try_new(ctx) {
|
|
||||||
Ok(ssl) => ssl,
|
|
||||||
Err(err) => return Err(err)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut ssl = SslStream {
|
let mut ssl = SslStream {
|
||||||
stream: stream,
|
stream: stream,
|
||||||
ssl: ssl,
|
ssl: ssl,
|
||||||
|
|
@ -463,6 +480,17 @@ impl<S: Stream> SslStream<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempts to create a new SSL stream
|
||||||
|
pub fn try_new(ctx: &SslContext, stream: S) -> Result<SslStream<S>,
|
||||||
|
SslError> {
|
||||||
|
let ssl = match Ssl::try_new(ctx) {
|
||||||
|
Ok(ssl) => ssl,
|
||||||
|
Err(err) => return Err(err)
|
||||||
|
};
|
||||||
|
|
||||||
|
SslStream::new_from(ssl, stream)
|
||||||
|
}
|
||||||
|
|
||||||
/// A convenience wrapper around `try_new`.
|
/// A convenience wrapper around `try_new`.
|
||||||
pub fn new(ctx: &SslContext, stream: S) -> SslStream<S> {
|
pub fn new(ctx: &SslContext, stream: S) -> SslStream<S> {
|
||||||
match SslStream::try_new(ctx, stream) {
|
match SslStream::try_new(ctx, stream) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue