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

SslStream sketch

parent 58eb7ab5
Loading
Loading
Loading
Loading
+23 −8
Original line number Diff line number Diff line
#[doc(hidden)];

use std::libc::{c_int, c_void};

pub type SSL_CTX = c_void;
pub type SSL_METHOD = c_void;
pub type SSL = c_void;
pub type BIO = c_void;
pub type BIO_METHOD = c_void;

#[link_args = "-lssl"]
extern "C" {
    fn SSL_library_init() -> c_int;
    fn SSL_load_error_strings();

    fn SSL_CTX_new(method: *SSL_METHOD) -> *SSL_CTX;
    fn SSLv23_method() -> *SSL_METHOD;
    fn SSL_CTX_free(ctx: *SSL_CTX);
}
extern "C" { }

externfn!(fn SSL_library_init() -> c_int)
externfn!(fn SSL_load_error_strings())

externfn!(fn SSLv23_method() -> *SSL_METHOD)
externfn!(fn SSL_CTX_new(method: *SSL_METHOD) -> *SSL_CTX)
externfn!(fn SSL_CTX_free(ctx: *SSL_CTX))

externfn!(fn SSL_new(ctx: *SSL_CTX) -> *SSL)
externfn!(fn SSL_free(ssl: *SSL))
externfn!(fn SSL_set_bio(ssl: *SSL, rbio: *BIO, wbio: *BIO))
externfn!(fn SSL_set_connect_state(ssl: *SSL))
externfn!(fn SSL_do_handshake(ssl: *SSL))

externfn!(fn BIO_s_mem() -> *BIO_METHOD)
externfn!(fn BIO_new(type_: *BIO_METHOD) -> *BIO)
externfn!(fn BIO_free(a: *BIO) -> c_int)
+97 −5
Original line number Diff line number Diff line
use std::rt::io::{Stream, Decorator};
use std::unstable::atomics::{AtomicBool, INIT_ATOMIC_BOOL, Acquire, Release};
use std::task;
use std::ptr;

mod ffi;

static mut STARTED_INIT: AtomicBool = INIT_ATOMIC_BOOL;
static mut FINISHED_INIT: AtomicBool = INIT_ATOMIC_BOOL;

#[fixed_stack_segment]
pub fn init() {
    unsafe {
        if STARTED_INIT.swap(true, Acquire) {
@@ -27,7 +28,6 @@ pub enum SslMethod {
}

impl SslMethod {
    #[fixed_stack_segment]
    unsafe fn to_raw(&self) -> *ffi::SSL_METHOD {
        match *self {
            Sslv23 => ffi::SSLv23_method()
@@ -40,18 +40,110 @@ pub struct SslCtx {
}

impl Drop for SslCtx {
    #[fixed_stack_segment]
    fn drop(&mut self) {
        unsafe { ffi::SSL_CTX_free(self.ctx); }
    }
}

impl SslCtx {
    #[fixed_stack_segment]
    pub fn new(method: SslMethod) -> SslCtx {
        init();

        let ctx = unsafe { ffi::SSL_CTX_new(method.to_raw()) };
        assert!(ctx != ptr::null());

        SslCtx {
            ctx: unsafe { ffi::SSL_CTX_new(method.to_raw()) }
            ctx: ctx
        }
    }
}

struct Ssl {
    ssl: *ffi::SSL
}

impl Drop for Ssl {
    fn drop(&mut self) {
        unsafe { ffi::SSL_free(self.ssl); }
    }
}

impl Ssl {
    fn new(ctx: &SslCtx) -> Ssl {
        let ssl = unsafe { ffi::SSL_new(ctx.ctx) };
        assert!(ssl != ptr::null());

        Ssl { ssl: ssl }
    }

    fn set_bio(&self, rbio: &MemBio, wbio: &MemBio) {
        unsafe { ffi::SSL_set_bio(self.ssl, rbio.bio, wbio.bio); }
    }

    fn set_connect_state(&self) {
        unsafe { ffi::SSL_set_connect_state(self.ssl); }
    }
}

struct MemBio {
    bio: *ffi::BIO
}

impl Drop for MemBio {
    fn drop(&mut self) {
        unsafe { ffi::BIO_free(self.bio); }
    }
}

impl MemBio {
    fn new() -> MemBio {
        let bio = unsafe { ffi::BIO_new(ffi::BIO_s_mem()) };
        assert!(bio != ptr::null());

        MemBio { bio: bio }
    }
}

pub struct SslStream<S> {
    priv ctx: SslCtx,
    priv ssl: Ssl,
    priv rbio: MemBio,
    priv wbio: MemBio,
    priv stream: S
}

impl<S: Stream> SslStream<S> {
    pub fn new(ctx: SslCtx, stream: S) -> SslStream<S> {
        let ssl = Ssl::new(&ctx);

        let rbio = MemBio::new();
        let wbio = MemBio::new();

        ssl.set_bio(&rbio, &wbio);
        ssl.set_connect_state();

        let stream = SslStream {
            ctx: ctx,
            ssl: ssl,
            rbio: rbio,
            wbio: wbio,
            stream: stream
        }

        stream
    }
}

impl<S: Stream> Decorator<S> for SslStream<S> {
    fn inner(self) -> S {
        self.stream
    }

    fn inner_ref<'a>(&'a self) -> &'a S {
        &self.stream
    }

    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut S {
        &mut self.stream
    }
}
+9 −1
Original line number Diff line number Diff line
extern mod ssl;

use ssl::{Sslv23, SslCtx};
use std::rt::io::net::tcp::TcpStream;

use ssl::{Sslv23, SslCtx, SslStream};

#[test]
fn test_new_ctx() {
    SslCtx::new(Sslv23);
}

#[test]
fn test_new_sslstream() {
    let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap());
    let stream = SslStream::new(SslCtx::new(Sslv23), stream);
}