diff --git a/Cargo.toml b/Cargo.toml index 321873e90ab034b3eeb49fd126d9c12738108a4a..c56b593d55d119e59ef92704dc384bdd134ac576 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "openssl" -version = "0.2.3" +version = "0.2.8" authors = ["Steven Fackler "] license = "Apache-2.0" description = "OpenSSL bindings" @@ -17,4 +17,4 @@ aes_xts = ["openssl-sys/aes_xts"] [dependencies.openssl-sys] path = "openssl-sys" -version = "0.2.3" +version = "0.2.8" diff --git a/README.md b/README.md index 427f6e47a32d22487d12563b7fe4064461db41f7..58a2285be156def0cab51dc320e24bdf4915d491 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ For some reason, the OpenSSL distribution for Windows is structured differently, 2. Run the installer, making note of where it's installing OpenSSL. The option to copy the libraries to the Windows system directory or `[OpenSSL folder]/bin` is your choice. The latter is probably preferable, and the default. 3. Navigate to `[OpenSSL folder]/lib/MinGW/`, and copy `libeay32.a` and `ssleay32.a` (If 64-bit, then they will have `64` instead of `32`.) to your Rust install's libs folder. The default should be: * 32-bit: `C:\Program Files (x86)\Rust\bin\rustlib\i686-pc-mingw32\lib` - * 64-bit: TODO + * 64-bit: `C:\Program Files (x86)\Rust\bin\rustlib\x86_64-pc-windows-gnu\lib` 4. Rename `libeay32.a` and `ssleay32.a` to `libcrypto.a` and `libssl.a`, respectively. 5. Run `cargo build`. diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 60ebc8c352d0b20b0d8db18945b28bfbef20d16f..b9695f4905bd527845306b017c012acf346a0312 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "openssl-sys" -version = "0.2.3" +version = "0.2.8" authors = ["Alex Crichton ", "Steven Fackler "] license = "MIT" diff --git a/openssl-sys/src/build.rs b/openssl-sys/src/build.rs index 53c047b2857f60ef7604b37d5b1ca7778b676556..ca71f79125e2fc124eb78457908d211e494ed3f5 100644 --- a/openssl-sys/src/build.rs +++ b/openssl-sys/src/build.rs @@ -9,9 +9,14 @@ fn main() { if pkg_config::find_library("openssl").is_err() { - let mut flags = " -l crypto -l ssl".to_string(); - let target = os::getenv("TARGET").unwrap(); + let is_android = target.find_str("android").is_some(); + + let mut flags = if is_android { + " -l crypto:static -l ssl:static" + } else { + " -l crypto -l ssl" + }.to_string(); let win_pos = target.find_str("windows") .or(target.find_str("win32")) @@ -23,7 +28,7 @@ fn main() { flags.push_str(" -l gdi32 -l wsock32"); } - if target.find_str("android").is_some() { + if is_android { let path = os::getenv("OPENSSL_PATH").expect("Android does not provide openssl libraries, please \ build them yourselves (instructions in the README) \ and provide their location through $OPENSSL_PATH."); diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 68d2d6dc64db3f140556f408ce3a01982624e2e9..48fac1d2a0782810593f84d080435cda8e168009 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -2,7 +2,6 @@ #![allow(dead_code)] extern crate libc; -extern crate rustrt; #[cfg(feature = "libressl-pnacl-sys")] extern crate "libressl-pnacl-sys" as _for_linkage; @@ -10,7 +9,7 @@ extern crate "libressl-pnacl-sys" as _for_linkage; use libc::{c_void, c_int, c_char, c_ulong, c_long, c_uint, c_uchar, size_t}; use std::mem; use std::ptr; -use rustrt::mutex::NativeMutex; +use std::sync::{StaticMutex, StaticMutexGuard, MUTEX_INIT}; use std::sync::{Once, ONCE_INIT}; pub type ASN1_INTEGER = c_void; @@ -49,6 +48,8 @@ pub struct EVP_MD_CTX { update: *mut c_void } +impl Copy for EVP_MD_CTX {} + #[repr(C)] pub struct HMAC_CTX { md: *mut EVP_MD, @@ -59,6 +60,8 @@ pub struct HMAC_CTX { key: [c_uchar, ..128] } +impl Copy for HMAC_CTX {} + #[repr(C)] pub struct X509V3_CTX { flags: c_int, @@ -72,6 +75,8 @@ pub struct X509V3_CTX { // Maybe more here } +impl Copy for X509V3_CTX {} + #[repr(C)] pub struct BIGNUM { pub d: *mut c_void, @@ -81,6 +86,8 @@ pub struct BIGNUM { pub flags: c_int, } +impl Copy for BIGNUM {} + #[repr(C)] pub struct BIGNUM_PTR { pub ptr: *mut BIGNUM, @@ -189,7 +196,8 @@ pub const X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE: c_int = 45; pub const X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: c_int = 53; pub const X509_V_OK: c_int = 0; -static mut MUTEXES: *mut Vec = 0 as *mut Vec; +static mut MUTEXES: *mut Vec = 0 as *mut Vec; +static mut GUARDS: *mut Vec> = 0 as *mut Vec>; extern fn locking_function(mode: c_int, n: c_int, _file: *const c_char, _line: c_int) { @@ -197,9 +205,9 @@ extern fn locking_function(mode: c_int, n: c_int, _file: *const c_char, let mutex = &(*MUTEXES)[n as uint]; if mode & CRYPTO_LOCK != 0 { - mutex.lock_noguard(); + (*GUARDS)[n as uint] = Some(mutex.lock()); } else { - mutex.unlock_noguard(); + &(*GUARDS)[n as uint].take(); } } } @@ -213,8 +221,10 @@ pub fn init() { SSL_load_error_strings(); let num_locks = CRYPTO_num_locks(); - let mutexes = box Vec::from_fn(num_locks as uint, |_| NativeMutex::new()); + let mutexes = box Vec::from_fn(num_locks as uint, |_| MUTEX_INIT); MUTEXES = mem::transmute(mutexes); + let guards: Box>> = box Vec::from_fn(num_locks as uint, |_| None); + GUARDS = mem::transmute(guards); CRYPTO_set_locking_callback(locking_function); }) diff --git a/src/bn/mod.rs b/src/bn/mod.rs index 7605fee0f19685ae02f7c983c8894c9bbaebe4a1..a4d2330278787ad78571a456f46789402b9f9d9d 100644 --- a/src/bn/mod.rs +++ b/src/bn/mod.rs @@ -7,6 +7,7 @@ use ssl::error::SslError; pub struct BigNum(*mut ffi::BIGNUM); +#[deriving(Copy)] #[repr(C)] pub enum RNGProperty { MsbMaybeZero = -1, @@ -25,7 +26,7 @@ macro_rules! with_ctx( r } }); -) +); macro_rules! with_bn( ($name:ident, $action:block) => ({ @@ -41,7 +42,7 @@ macro_rules! with_bn( Err(err) => Err(err), } }); -) +); macro_rules! with_bn_in_ctx( ($name:ident, $ctx_name:ident, $action:block) => ({ @@ -65,7 +66,7 @@ macro_rules! with_bn_in_ctx( Err(err) => Err(err), } }); -) +); impl BigNum { pub fn new() -> Result { @@ -441,45 +442,45 @@ pub mod unchecked { use ffi; use super::{BigNum}; - impl Add for BigNum { - fn add(&self, oth: &BigNum) -> BigNum { + impl<'a> Add<&'a BigNum, BigNum> for &'a BigNum { + fn add(self, oth: &'a BigNum) -> BigNum { self.checked_add(oth).unwrap() } } - impl Sub for BigNum { - fn sub(&self, oth: &BigNum) -> BigNum { + impl<'a> Sub<&'a BigNum, BigNum> for &'a BigNum { + fn sub(self, oth: &'a BigNum) -> BigNum { self.checked_sub(oth).unwrap() } } - impl Mul for BigNum { - fn mul(&self, oth: &BigNum) -> BigNum { + impl<'a> Mul<&'a BigNum, BigNum> for &'a BigNum { + fn mul(self, oth: &'a BigNum) -> BigNum { self.checked_mul(oth).unwrap() } } - impl Div for BigNum { - fn div(&self, oth: &BigNum) -> BigNum { + impl<'a> Div<&'a BigNum, BigNum> for &'a BigNum { + fn div(self, oth: &'a BigNum) -> BigNum { self.checked_div(oth).unwrap() } } - impl Rem for BigNum { - fn rem(&self, oth: &BigNum) -> BigNum { + impl<'a> Rem<&'a BigNum, BigNum> for &'a BigNum { + fn rem(self, oth: &'a BigNum) -> BigNum { self.checked_mod(oth).unwrap() } } - impl Shl for BigNum { - fn shl(&self, n: &i32) -> BigNum { - self.checked_shl(n).unwrap() + impl<'a> Shl for &'a BigNum { + fn shl(self, n: i32) -> BigNum { + self.checked_shl(&n).unwrap() } } - impl Shr for BigNum { - fn shr(&self, n: &i32) -> BigNum { - self.checked_shr(n).unwrap() + impl<'a> Shr for &'a BigNum { + fn shr(self, n: i32) -> BigNum { + self.checked_shr(&n).unwrap() } } @@ -497,7 +498,7 @@ pub mod unchecked { } impl Neg for BigNum { - fn neg(&self) -> BigNum { + fn neg(self) -> BigNum { let mut n = self.clone(); n.negate(); n diff --git a/src/crypto/hash.rs b/src/crypto/hash.rs index b5d0eab5d8911f7d4d801ad48eb1923abb5e2619..2a1815266328df8c410bd6f7f6a1395e5608d85f 100644 --- a/src/crypto/hash.rs +++ b/src/crypto/hash.rs @@ -4,6 +4,7 @@ use std::io; use ffi; +#[deriving(Copy)] pub enum HashType { MD5, SHA1, @@ -134,7 +135,7 @@ mod tests { } fn compare(calced_raw: Vec, hashtest: &HashTest) { - let calced = calced_raw.as_slice().to_hex().into_string(); + let calced = calced_raw.as_slice().to_hex().to_string(); if calced != hashtest.expected_output { println!("Test failed - {} != {}", calced, hashtest.expected_output); diff --git a/src/crypto/hmac.rs b/src/crypto/hmac.rs index 8096a9480641effbee6bd23553fd3c0cd48dda81..aab0c01448d9b77fd830db389010d1faf4bbc80f 100644 --- a/src/crypto/hmac.rs +++ b/src/crypto/hmac.rs @@ -55,7 +55,7 @@ impl HMAC { let mut res = Vec::from_elem(self.len, 0u8); let mut outlen = 0; ffi::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut outlen); - assert!(self.len == outlen as uint) + assert!(self.len == outlen as uint); res } } diff --git a/src/crypto/pkey.rs b/src/crypto/pkey.rs index 146d2aa32799f3a717a5e46ac09db65bdcc4efd5..bab7addc945f2856f2f68559ff1d139325390d46 100644 --- a/src/crypto/pkey.rs +++ b/src/crypto/pkey.rs @@ -6,7 +6,7 @@ use crypto::hash::HashType; use ffi; use ssl::error::{SslError, StreamError}; - +#[deriving(Copy)] enum Parts { Neither, Public, @@ -14,6 +14,7 @@ enum Parts { } /// Represents a role an asymmetric key might be appropriate for. +#[deriving(Copy)] pub enum Role { Encrypt, Decrypt, @@ -22,6 +23,7 @@ pub enum Role { } /// Type of encryption padding to use. +#[deriving(Copy)] pub enum EncryptionPadding { OAEP, PKCS1v15 diff --git a/src/crypto/symm.rs b/src/crypto/symm.rs index 998d351cf2e21e6829451e27fd5774a865cece1d..61365f2e160909e298a8bc8fbf46c75a36a3d756 100644 --- a/src/crypto/symm.rs +++ b/src/crypto/symm.rs @@ -2,12 +2,14 @@ use libc::{c_int}; use ffi; +#[deriving(Copy)] pub enum Mode { Encrypt, Decrypt, } #[allow(non_camel_case_types)] +#[deriving(Copy)] pub enum Type { AES_128_ECB, AES_128_CBC, diff --git a/src/ssl/mod.rs b/src/ssl/mod.rs index 6112bc8d48f712e47803bef9b4b66927204ee67a..436735968d1ca167ec7324968f52d4272be85736 100644 --- a/src/ssl/mod.rs +++ b/src/ssl/mod.rs @@ -33,6 +33,7 @@ fn init() { /// Determines the SSL method supported #[deriving(Show, Hash, PartialEq, Eq)] #[allow(non_camel_case_types)] +#[deriving(Copy)] pub enum SslMethod { #[cfg(feature = "sslv2")] /// Only support the SSLv2 protocol, requires `feature="sslv2"` @@ -68,6 +69,7 @@ impl SslMethod { } /// Determines the type of certificate verification used +#[deriving(Copy)] #[repr(i32)] pub enum SslVerifyMode { /// Verify that the server's certificate is trusted @@ -91,8 +93,9 @@ fn get_verify_data_idx() -> c_int { unsafe { INIT.doit(|| { + let f: ffi::CRYPTO_EX_free = free_data_box::; let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, - None, Some(free_data_box::)); + None, Some(f)); assert!(idx >= 0); VERIFY_DATA_IDX = idx; }); @@ -197,7 +200,9 @@ impl SslContext { unsafe { ffi::SSL_CTX_set_ex_data(self.ctx, VERIFY_IDX, mem::transmute(verify)); - ffi::SSL_CTX_set_verify(self.ctx, mode as c_int, Some(raw_verify)); + let f: extern fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int = + raw_verify; + ffi::SSL_CTX_set_verify(self.ctx, mode as c_int, Some(f)); } } @@ -214,7 +219,9 @@ impl SslContext { mem::transmute(Some(verify))); ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::(), mem::transmute(data)); - ffi::SSL_CTX_set_verify(self.ctx, mode as c_int, Some(raw_verify_with_data::)); + let f: extern fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int = + raw_verify_with_data::; + ffi::SSL_CTX_set_verify(self.ctx, mode as c_int, Some(f)); } } @@ -382,7 +389,7 @@ impl Ssl { } -#[deriving(FromPrimitive)] +#[deriving(FromPrimitive, Show)] #[repr(i32)] enum LibSslError { ErrorNone = ffi::SSL_ERROR_NONE, @@ -487,7 +494,7 @@ impl SslStream { LibSslError::ErrorWantWrite => { try_ssl_stream!(self.flush()) } LibSslError::ErrorZeroReturn => return Err(SslSessionClosed), LibSslError::ErrorSsl => return Err(SslError::get()), - _ => unreachable!() + err => panic!("unexpected error {}", err), } } } @@ -539,7 +546,7 @@ impl Writer for SslStream { let mut start = 0; while start < buf.len() { let ret = self.in_retry_wrapper(|ssl| { - ssl.write(buf.split_at(start).val1()) + ssl.write(buf.split_at(start).1) }); match ret { Ok(len) => start += len as uint, diff --git a/src/ssl/tests.rs b/src/ssl/tests.rs index e4414f841593595d44a2921f8c13a3da919616a2..6723fa5831521423a0e752d03946449eb830ad45 100644 --- a/src/ssl/tests.rs +++ b/src/ssl/tests.rs @@ -1,10 +1,11 @@ use serialize::hex::FromHex; -use std::io::{Writer}; use std::io::net::tcp::TcpStream; +use std::io::{Writer}; +use std::thread::Thread; use crypto::hash::HashType::{SHA256}; use ssl::SslMethod::Sslv23; -use ssl::{SslContext, SslStream}; +use ssl::{SslContext, SslStream, VerifyCallback}; use ssl::SslVerifyMode::SslVerifyPeer; use x509::{X509StoreContext}; @@ -52,7 +53,7 @@ fn test_verify_untrusted_callback_override_ok() { } let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SslVerifyPeer, Some(callback)); + ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback)); match SslStream::new(&ctx, stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {}", err) @@ -66,7 +67,7 @@ fn test_verify_untrusted_callback_override_bad() { } let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SslVerifyPeer, Some(callback)); + ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback)); assert!(SslStream::new(&ctx, stream).is_err()); } @@ -77,7 +78,7 @@ fn test_verify_trusted_callback_override_ok() { } let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SslVerifyPeer, Some(callback)); + ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback)); match ctx.set_CA_file(&Path::new("test/cert.pem")) { None => {} Some(err) => panic!("Unexpected error {}", err) @@ -95,7 +96,7 @@ fn test_verify_trusted_callback_override_bad() { } let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SslVerifyPeer, Some(callback)); + ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback)); match ctx.set_CA_file(&Path::new("test/cert.pem")) { None => {} Some(err) => panic!("Unexpected error {}", err) @@ -111,7 +112,7 @@ fn test_verify_callback_load_certs() { } let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SslVerifyPeer, Some(callback)); + ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback)); assert!(SslStream::new(&ctx, stream).is_ok()); } @@ -123,7 +124,7 @@ fn test_verify_trusted_get_error_ok() { } let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SslVerifyPeer, Some(callback)); + ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback)); match ctx.set_CA_file(&Path::new("test/cert.pem")) { None => {} Some(err) => panic!("Unexpected error {}", err) @@ -139,7 +140,7 @@ fn test_verify_trusted_get_error_err() { } let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); let mut ctx = SslContext::new(Sslv23).unwrap(); - ctx.set_verify(SslVerifyPeer, Some(callback)); + ctx.set_verify(SslVerifyPeer, Some(callback as VerifyCallback)); assert!(SslStream::new(&ctx, stream).is_err()); } @@ -198,7 +199,7 @@ fn test_clone() { let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); let mut stream = SslStream::new(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); let mut stream2 = stream.clone(); - spawn(proc() { + let _t = Thread::spawn(move || { stream2.write("GET /\r\n\r\n".as_bytes()).unwrap(); stream2.flush().unwrap(); }); diff --git a/src/x509/mod.rs b/src/x509/mod.rs index a06fe4e16b743cb481a412966650fa56e781ee63..c82eab113df620c1ad7158cce8ed9e1d5b4834e6 100644 --- a/src/x509/mod.rs +++ b/src/x509/mod.rs @@ -15,6 +15,7 @@ use ssl::error::{SslError, StreamError}; #[cfg(test)] mod tests; +#[deriving(Copy)] #[repr(i32)] pub enum X509FileType { PEM = ffi::X509_FILETYPE_PEM, @@ -22,6 +23,7 @@ pub enum X509FileType { Default = ffi::X509_FILETYPE_DEFAULT } +#[allow(missing_copy_implementations)] pub struct X509StoreContext { ctx: *mut ffi::X509_STORE_CTX } @@ -54,7 +56,7 @@ trait AsStr<'a> { fn as_str(&self) -> &'a str; } -#[deriving(Clone)] +#[deriving(Clone, Copy)] pub enum KeyUsage { DigitalSignature, NonRepudiation, @@ -84,7 +86,7 @@ impl AsStr<'static> for KeyUsage { } -#[deriving(Clone)] +#[deriving(Clone, Copy)] pub enum ExtKeyUsage { ServerAuth, ClientAuth, @@ -360,7 +362,7 @@ impl<'ctx> X509<'ctx> { } /// Reads certificate from PEM, takes ownership of handle - pub fn from_pem(reader: &mut Reader) -> Result, SslError> { + pub fn from_pem(reader: &mut R) -> Result, SslError> where R: Reader { let mut mem_bio = try!(MemBio::new()); let buf = try!(reader.read_to_end().map_err(StreamError)); try!(mem_bio.write(buf.as_slice()).map_err(StreamError)); @@ -402,7 +404,7 @@ impl<'ctx> X509<'ctx> { } /// Writes certificate as PEM - pub fn write_pem(&self, writer: &mut Writer) -> Result<(), SslError> { + pub fn write_pem(&self, writer: &mut W) -> Result<(), SslError> where W: Writer{ let mut mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), @@ -430,6 +432,7 @@ pub struct X509Name<'x> { macro_rules! make_validation_error( ($ok_val:ident, $($name:ident = $val:ident,)+) => ( + #[deriving(Copy)] pub enum X509ValidationError { $($name,)+ X509UnknownError(c_int) @@ -446,7 +449,7 @@ macro_rules! make_validation_error( } } ) -) +); make_validation_error!(X509_V_OK, X509UnableToGetIssuerCert = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, @@ -502,7 +505,7 @@ make_validation_error!(X509_V_OK, X509UnsupportedNameSyntax = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX, X509CrlPathValidationError= X509_V_ERR_CRL_PATH_VALIDATION_ERROR, X509ApplicationVerification = X509_V_ERR_APPLICATION_VERIFICATION, -) +); #[test]