Start of x509 interface

This commit is contained in:
Steven Fackler 2013-11-16 20:21:48 -08:00
parent 5857889ceb
commit f8be641536
3 changed files with 45 additions and 7 deletions

2
ffi.rs
View File

@ -9,6 +9,7 @@ pub type SSL = c_void;
pub type BIO = c_void; pub type BIO = c_void;
pub type BIO_METHOD = c_void; pub type BIO_METHOD = c_void;
pub type X509_STORE_CTX = c_void; pub type X509_STORE_CTX = c_void;
pub type X509 = c_void;
pub type CRYPTO_EX_DATA = c_void; pub type CRYPTO_EX_DATA = c_void;
pub type CRYPTO_EX_new = extern "C" fn(parent: *c_void, ptr: *c_void, pub type CRYPTO_EX_new = extern "C" fn(parent: *c_void, ptr: *c_void,
@ -62,6 +63,7 @@ extern "C" {
pub fn X509_STORE_CTX_get_ex_data(ctx: *X509_STORE_CTX, idx: c_int) pub fn X509_STORE_CTX_get_ex_data(ctx: *X509_STORE_CTX, idx: c_int)
-> *c_void; -> *c_void;
pub fn X509_STORE_CTX_get_current_cert(ct: *X509_STORE_CTX) -> *X509;
pub fn SSL_new(ctx: *SSL_CTX) -> *SSL; pub fn SSL_new(ctx: *SSL_CTX) -> *SSL;
pub fn SSL_free(ssl: *SSL); pub fn SSL_free(ssl: *SSL);

28
lib.rs
View File

@ -82,15 +82,18 @@ extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *ffi::X509_STORE_CTX)
let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, idx); let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, idx);
let verify: Option<VerifyCallback> = cast::transmute(verify); let verify: Option<VerifyCallback> = cast::transmute(verify);
let ctx = X509StoreContext { ctx: x509_ctx };
match verify { match verify {
None => preverify_ok, None => preverify_ok,
Some(verify) => verify(preverify_ok != 0) as c_int Some(verify) => verify(preverify_ok != 0, ctx) as c_int
} }
} }
} }
/// The signature of functions that can be used to manually verify certificates /// The signature of functions that can be used to manually verify certificates
pub type VerifyCallback = extern "Rust" fn(preverify_ok: bool) -> bool; pub type VerifyCallback = extern "Rust" fn(preverify_ok: bool,
x509_ctx: X509StoreContext) -> bool;
/// An SSL context object /// An SSL context object
pub struct SslContext { pub struct SslContext {
@ -151,6 +154,27 @@ impl SslContext {
} }
} }
pub struct X509StoreContext {
priv ctx: *ffi::X509_STORE_CTX
}
impl X509StoreContext {
pub fn get_current_cert(&self) -> Option<X509> {
let ptr = unsafe { ffi::X509_STORE_CTX_get_current_cert(self.ctx) };
if ptr.is_null() {
None
} else {
Some(X509 { x509: ptr })
}
}
}
/// A public key certificate
pub struct X509 {
priv x509: *ffi::X509
}
struct Ssl { struct Ssl {
ssl: *ffi::SSL ssl: *ffi::SSL
} }

22
test.rs
View File

@ -4,7 +4,7 @@ use std::io::Writer;
use std::io::net::tcp::TcpStream; use std::io::net::tcp::TcpStream;
use std::str; use std::str;
use lib::{Sslv23, SslContext, SslStream, SslVerifyPeer}; use lib::{Sslv23, SslContext, SslStream, SslVerifyPeer, X509StoreContext};
mod lib; mod lib;
@ -47,7 +47,7 @@ fn test_verify_trusted() {
#[test] #[test]
fn test_verify_untrusted_callback_override_ok() { fn test_verify_untrusted_callback_override_ok() {
fn callback(_preverify_ok: bool) -> bool { fn callback(_preverify_ok: bool, _x509_ctx: X509StoreContext) -> bool {
true true
} }
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap(); let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap();
@ -61,7 +61,7 @@ fn test_verify_untrusted_callback_override_ok() {
#[test] #[test]
fn test_verify_untrusted_callback_override_bad() { fn test_verify_untrusted_callback_override_bad() {
fn callback(_preverify_ok: bool) -> bool { fn callback(_preverify_ok: bool, _x509_ctx: X509StoreContext) -> bool {
false false
} }
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap(); let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap();
@ -72,7 +72,7 @@ fn test_verify_untrusted_callback_override_bad() {
#[test] #[test]
fn test_verify_trusted_callback_override_ok() { fn test_verify_trusted_callback_override_ok() {
fn callback(_preverify_ok: bool) -> bool { fn callback(_preverify_ok: bool, _x509_ctx: X509StoreContext) -> bool {
true true
} }
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap(); let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap();
@ -90,7 +90,7 @@ fn test_verify_trusted_callback_override_ok() {
#[test] #[test]
fn test_verify_trusted_callback_override_bad() { fn test_verify_trusted_callback_override_bad() {
fn callback(_preverify_ok: bool) -> bool { fn callback(_preverify_ok: bool, _x509_ctx: X509StoreContext) -> bool {
false false
} }
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap(); let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap();
@ -103,6 +103,18 @@ fn test_verify_trusted_callback_override_bad() {
assert!(SslStream::try_new(&ctx, stream).is_err()); assert!(SslStream::try_new(&ctx, stream).is_err());
} }
#[test]
fn test_verify_callback_load_certs() {
fn callback(_preverify_ok: bool, x509_ctx: X509StoreContext) -> bool {
assert!(x509_ctx.get_current_cert().is_some());
true
}
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap();
let mut ctx = SslContext::new(Sslv23);
ctx.set_verify(SslVerifyPeer, Some(callback));
assert!(SslStream::try_new(&ctx, stream).is_ok());
}
#[test] #[test]
fn test_write() { fn test_write() {
let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap(); let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()).unwrap();