diff --git a/src/ssl/ffi.rs b/src/ssl/ffi.rs index 4677c1890c8386ebbb8963783cb3cefc0eb3a772..3fa6c9f4fab8867e2d880c194a85d9a1179abe6c 100644 --- a/src/ssl/ffi.rs +++ b/src/ssl/ffi.rs @@ -38,6 +38,10 @@ pub static SSL_ERROR_WANT_ACCEPT: c_int = 8; pub static SSL_VERIFY_NONE: c_int = 0; 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_ERR_UNABLE_TO_GET_ISSUER_CERT: c_int = 2; pub static X509_V_ERR_UNABLE_TO_GET_CRL: c_int = 3; @@ -140,6 +144,8 @@ extern "C" { pub fn SSL_get_rbio(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_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_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; diff --git a/src/ssl/mod.rs b/src/ssl/mod.rs index 7c9b2d60efae3298f9588292792d64316cffcfea..82301086bc3c4862ec4c690b4ecd2bb7bec9554f 100644 --- a/src/ssl/mod.rs +++ b/src/ssl/mod.rs @@ -362,6 +362,29 @@ impl Ssl { 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)]