Commit f4b70067 authored by Steven Fackler's avatar Steven Fackler
Browse files

Don't allow mutation of SslContexts

SslContext is reference counted and the various setter methods don't
take out locks where necessary. Fix this by adding a builder for the
context.
parent a5a3f557
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ mod tests {
    #[test]
    #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
    fn test_dh_rfc5114() {
        let mut ctx = SslContext::new(SslMethod::tls()).unwrap();
        let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
        let dh1 = DH::get_1024_160().unwrap();
        ctx.set_tmp_dh(&dh1).unwrap();
        let dh2 = DH::get_2048_224().unwrap();
@@ -112,7 +112,7 @@ mod tests {

    #[test]
    fn test_dh() {
        let mut ctx = SslContext::new(SslMethod::tls()).unwrap();
        let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
        let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435\
                                      E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF429\
                                      6D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C02\
@@ -142,7 +142,7 @@ mod tests {

    #[test]
    fn test_dh_from_pem() {
        let mut ctx = SslContext::new(SslMethod::tls()).unwrap();
        let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
        let params = include_bytes!("../test/dhparams.pem");
        let dh = DH::from_pem(params).ok().expect("Failed to load PEM");
        ctx.set_tmp_dh(&dh).unwrap();
+56 −29
Original line number Diff line number Diff line
@@ -335,20 +335,34 @@ pub enum SniError {
    NoAck,
}

/// A borrowed SSL context object.
pub struct SslContextRef(Opaque);
pub struct SslContextBuilder(*mut ffi::SSL_CTX);

impl SslContextRef {
    pub unsafe fn from_ptr<'a>(ctx: *mut ffi::SSL_CTX) -> &'a SslContextRef {
        &*(ctx as *mut _)
impl Drop for SslContextBuilder {
    fn drop(&mut self) {
        unsafe { ffi::SSL_CTX_free(self.as_ptr()) }
    }
}

    pub unsafe fn from_ptr_mut<'a>(ctx: *mut ffi::SSL_CTX) -> &'a mut SslContextRef {
        &mut *(ctx as *mut _)
impl SslContextBuilder {
    pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
        init();

        let mut ctx = unsafe {
            let ctx = try!(cvt_p(ffi::SSL_CTX_new(method.as_ptr())));
            SslContextBuilder::from_ptr(ctx)
        };

        try!(ctx.set_mode(ffi::SSL_MODE_AUTO_RETRY | ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER));

        Ok(ctx)
    }

    pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
        SslContextBuilder(ctx)
    }

    pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
        self as *const _ as *mut _
        self.0
    }

    /// Configures the certificate verification method for new connections.
@@ -409,7 +423,7 @@ impl SslContextRef {

    pub fn set_tmp_dh(&mut self, dh: &DH) -> Result<(), ErrorStack> {
        unsafe {
            cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as i32).map(|_| ())
            cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ())
        }
    }

@@ -517,13 +531,6 @@ impl SslContextRef {
        }
    }

    /// Check consistency of private key and certificate
    pub fn check_private_key(&mut self) -> Result<(), ErrorStack> {
        unsafe {
            cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ())
        }
    }

    pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
        let cipher_list = CString::new(cipher_list).unwrap();
        unsafe {
@@ -628,6 +635,36 @@ impl SslContextRef {
            Ok(())
        }
    }

    /// Checks consistency between the private key and certificate.
    pub fn check_private_key(&self) -> Result<(), ErrorStack> {
        unsafe {
            cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ())
        }
    }

    pub fn build(self) -> SslContext {
        let ctx = SslContext(self.0);
        mem::forget(self);
        ctx
    }
}

/// A borrowed SSL context object.
pub struct SslContextRef(Opaque);

impl SslContextRef {
    pub unsafe fn from_ptr<'a>(ctx: *mut ffi::SSL_CTX) -> &'a SslContextRef {
        &*(ctx as *mut _)
    }

    pub unsafe fn from_ptr_mut<'a>(ctx: *mut ffi::SSL_CTX) -> &'a mut SslContextRef {
        &mut *(ctx as *mut _)
    }

    pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
        self as *const _ as *mut _
    }
}

/// An owned SSL context object.
@@ -677,18 +714,8 @@ impl DerefMut for SslContext {
}

impl SslContext {
    /// Creates a new SSL context.
    pub fn new(method: SslMethod) -> Result<SslContext, ErrorStack> {
        init();

        let mut ctx = unsafe {
            let ctx = try!(cvt_p(ffi::SSL_CTX_new(method.as_ptr())));
            SslContext::from_ptr(ctx)
        };

        try!(ctx.set_mode(ffi::SSL_MODE_AUTO_RETRY | ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER));

        Ok(ctx)
    pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
        SslContextBuilder::new(method)
    }

    pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContext {
+96 −96

File changed.

Preview size limit exceeded, changes collapsed.