Merge branch 'release-v0.7.11' into release
This commit is contained in:
commit
4294511f2b
|
|
@ -6,8 +6,7 @@ addons:
|
||||||
- gcc-arm-linux-gnueabihf
|
- gcc-arm-linux-gnueabihf
|
||||||
rust:
|
rust:
|
||||||
- nightly
|
- nightly
|
||||||
- beta
|
- 1.8.0
|
||||||
- 1.4.0
|
|
||||||
os:
|
os:
|
||||||
- osx
|
- osx
|
||||||
- linux
|
- linux
|
||||||
|
|
@ -19,7 +18,7 @@ matrix:
|
||||||
# include:
|
# include:
|
||||||
# - os: linux
|
# - os: linux
|
||||||
# env: TARGET=arm-unknown-linux-gnueabihf TEST_FEATURES=true
|
# env: TARGET=arm-unknown-linux-gnueabihf TEST_FEATURES=true
|
||||||
# rust: 1.4.0
|
# rust: 1.8.0
|
||||||
exclude:
|
exclude:
|
||||||
- os: osx
|
- os: osx
|
||||||
env: TEST_FEATURES=true
|
env: TEST_FEATURES=true
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[](https://travis-ci.org/sfackler/rust-openssl)
|
[](https://travis-ci.org/sfackler/rust-openssl)
|
||||||
|
|
||||||
[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.7.10/openssl).
|
[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.7.11/openssl).
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ environment:
|
||||||
# - TARGET: x86_64-pc-windows-msvc
|
# - TARGET: x86_64-pc-windows-msvc
|
||||||
# BITS: 64
|
# BITS: 64
|
||||||
install:
|
install:
|
||||||
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2g.exe"
|
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2h.exe"
|
||||||
- Win%BITS%OpenSSL-1_0_2g.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
|
- Win%BITS%OpenSSL-1_0_2h.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
|
||||||
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.5.0-${env:TARGET}.exe"
|
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.8.0-${env:TARGET}.exe"
|
||||||
- rust-1.5.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
|
- rust-1.8.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
|
||||||
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
|
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
|
||||||
- SET PATH=%PATH%;C:\MinGW\bin
|
- SET PATH=%PATH%;C:\MinGW\bin
|
||||||
- rustc -V
|
- rustc -V
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
[package]
|
[package]
|
||||||
name = "openssl-sys-extras"
|
name = "openssl-sys-extras"
|
||||||
version = "0.7.10"
|
version = "0.7.11"
|
||||||
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "Extra FFI bindings to OpenSSL that require a C shim"
|
description = "Extra FFI bindings to OpenSSL that require a C shim"
|
||||||
repository = "https://github.com/sfackler/rust-openssl"
|
repository = "https://github.com/sfackler/rust-openssl"
|
||||||
documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.10/openssl_sys_extras"
|
documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.11/openssl_sys_extras"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
@ -13,7 +13,7 @@ ecdh_auto = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
openssl-sys = { version = "0.7.10", path = "../openssl-sys" }
|
openssl-sys = { version = "0.7.11", path = "../openssl-sys" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gcc = "0.3"
|
gcc = "0.3"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#![allow(non_upper_case_globals, non_snake_case)]
|
#![allow(non_upper_case_globals, non_snake_case)]
|
||||||
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.10")]
|
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.11")]
|
||||||
|
|
||||||
extern crate openssl_sys;
|
extern crate openssl_sys;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
|
||||||
|
|
@ -3,32 +3,6 @@
|
||||||
#include <openssl/dh.h>
|
#include <openssl/dh.h>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__linux)
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <openssl/crypto.h>
|
|
||||||
|
|
||||||
unsigned long thread_id()
|
|
||||||
{
|
|
||||||
return (unsigned long) pthread_self();
|
|
||||||
}
|
|
||||||
|
|
||||||
void rust_openssl_set_id_callback() {
|
|
||||||
CRYPTO_set_id_callback(thread_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
// Openssl already handles Windows directly, so we don't
|
|
||||||
// need to explicitly set it
|
|
||||||
|
|
||||||
void rust_openssl_set_id_callback() {
|
|
||||||
// We don't know how to set the callback for arbitrary OSes
|
|
||||||
// Let openssl use its defaults and hope they work.
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10000000L
|
#if OPENSSL_VERSION_NUMBER < 0x10000000L
|
||||||
// Copied from openssl crypto/hmac/hmac.c
|
// Copied from openssl crypto/hmac/hmac.c
|
||||||
int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
|
int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
[package]
|
[package]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.7.10"
|
version = "0.7.11"
|
||||||
authors = ["Alex Crichton <alex@alexcrichton.com>",
|
authors = ["Alex Crichton <alex@alexcrichton.com>",
|
||||||
"Steven Fackler <sfackler@gmail.com>"]
|
"Steven Fackler <sfackler@gmail.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "FFI bindings to OpenSSL"
|
description = "FFI bindings to OpenSSL"
|
||||||
repository = "https://github.com/sfackler/rust-openssl"
|
repository = "https://github.com/sfackler/rust-openssl"
|
||||||
documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.10/openssl_sys"
|
documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.11/openssl_sys"
|
||||||
links = "openssl"
|
links = "openssl"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]
|
#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.10")]
|
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.11")]
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
|
|
@ -34,10 +34,23 @@ pub type X509_NAME = c_void;
|
||||||
pub type X509_NAME_ENTRY = c_void;
|
pub type X509_NAME_ENTRY = c_void;
|
||||||
pub type X509_REQ = c_void;
|
pub type X509_REQ = c_void;
|
||||||
pub type X509_STORE_CTX = c_void;
|
pub type X509_STORE_CTX = c_void;
|
||||||
pub type stack_st_X509_EXTENSION = c_void;
|
|
||||||
pub type stack_st_void = c_void;
|
|
||||||
pub type bio_st = c_void;
|
pub type bio_st = c_void;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct stack_st_X509_EXTENSION {
|
||||||
|
pub stack: _STACK,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct stack_st_GENERAL_NAME {
|
||||||
|
pub stack: _STACK,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct stack_st_void {
|
||||||
|
pub stack: _STACK,
|
||||||
|
}
|
||||||
|
|
||||||
pub type bio_info_cb = Option<unsafe extern "C" fn(*mut BIO,
|
pub type bio_info_cb = Option<unsafe extern "C" fn(*mut BIO,
|
||||||
c_int,
|
c_int,
|
||||||
*const c_char,
|
*const c_char,
|
||||||
|
|
@ -63,6 +76,15 @@ pub struct BIO_METHOD {
|
||||||
// so we can create static BIO_METHODs
|
// so we can create static BIO_METHODs
|
||||||
unsafe impl Sync for BIO_METHOD {}
|
unsafe impl Sync for BIO_METHOD {}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct _STACK {
|
||||||
|
pub num: c_int,
|
||||||
|
pub data: *mut *mut c_char,
|
||||||
|
pub sorted: c_int,
|
||||||
|
pub num_alloc: c_int,
|
||||||
|
pub comp: Option<unsafe extern "C" fn(*const c_void, *const c_void)>,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct RSA {
|
pub struct RSA {
|
||||||
pub pad: c_int,
|
pub pad: c_int,
|
||||||
|
|
@ -178,6 +200,17 @@ pub struct X509V3_CTX {
|
||||||
// Maybe more here
|
// Maybe more here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct GENERAL_NAME {
|
||||||
|
pub type_: c_int,
|
||||||
|
pub d: *mut c_void,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Copy for GENERAL_NAME {}
|
||||||
|
impl Clone for GENERAL_NAME {
|
||||||
|
fn clone(&self) -> GENERAL_NAME { *self }
|
||||||
|
}
|
||||||
|
|
||||||
impl Copy for X509V3_CTX {}
|
impl Copy for X509V3_CTX {}
|
||||||
impl Clone for X509V3_CTX {
|
impl Clone for X509V3_CTX {
|
||||||
fn clone(&self) -> X509V3_CTX { *self }
|
fn clone(&self) -> X509V3_CTX { *self }
|
||||||
|
|
@ -333,6 +366,16 @@ 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_ERR_UNSUPPORTED_NAME_SYNTAX: c_int = 53;
|
||||||
pub const X509_V_OK: c_int = 0;
|
pub const X509_V_OK: c_int = 0;
|
||||||
|
|
||||||
|
pub const GEN_OTHERNAME: c_int = 0;
|
||||||
|
pub const GEN_EMAIL: c_int = 1;
|
||||||
|
pub const GEN_DNS: c_int = 2;
|
||||||
|
pub const GEN_X400: c_int = 3;
|
||||||
|
pub const GEN_DIRNAME: c_int = 4;
|
||||||
|
pub const GEN_EDIPARTY: c_int = 5;
|
||||||
|
pub const GEN_URI: c_int = 6;
|
||||||
|
pub const GEN_IPADD: c_int = 7;
|
||||||
|
pub const GEN_RID: c_int = 8;
|
||||||
|
|
||||||
static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>;
|
static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>;
|
||||||
static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> = 0 as *mut Vec<Option<MutexGuard<'static, ()>>>;
|
static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> = 0 as *mut Vec<Option<MutexGuard<'static, ()>>>;
|
||||||
|
|
||||||
|
|
@ -527,6 +570,9 @@ extern "C" {
|
||||||
pub fn EVP_aes_256_cfb8() -> *const EVP_CIPHER;
|
pub fn EVP_aes_256_cfb8() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_rc4() -> *const EVP_CIPHER;
|
pub fn EVP_rc4() -> *const EVP_CIPHER;
|
||||||
|
|
||||||
|
pub fn EVP_des_cbc() -> *const EVP_CIPHER;
|
||||||
|
pub fn EVP_des_ecb() -> *const EVP_CIPHER;
|
||||||
|
|
||||||
pub fn EVP_BytesToKey(typ: *const EVP_CIPHER, md: *const EVP_MD,
|
pub fn EVP_BytesToKey(typ: *const EVP_CIPHER, md: *const EVP_MD,
|
||||||
salt: *const u8, data: *const u8, datalen: c_int,
|
salt: *const u8, data: *const u8, datalen: c_int,
|
||||||
count: c_int, key: *mut u8, iv: *mut u8) -> c_int;
|
count: c_int, key: *mut u8, iv: *mut u8) -> c_int;
|
||||||
|
|
@ -654,6 +700,16 @@ extern "C" {
|
||||||
pub fn SSL_get_version(ssl: *mut SSL) -> *const c_char;
|
pub fn SSL_get_version(ssl: *mut SSL) -> *const c_char;
|
||||||
pub fn SSL_state_string(ssl: *mut SSL) -> *const c_char;
|
pub fn SSL_state_string(ssl: *mut SSL) -> *const c_char;
|
||||||
pub fn SSL_state_string_long(ssl: *mut SSL) -> *const c_char;
|
pub fn SSL_state_string_long(ssl: *mut SSL) -> *const c_char;
|
||||||
|
pub fn SSL_set_verify(ssl: *mut SSL,
|
||||||
|
mode: c_int,
|
||||||
|
verify_callback: Option<extern fn(c_int, *mut X509_STORE_CTX) -> c_int>);
|
||||||
|
pub fn SSL_get_ex_new_index(argl: c_long, argp: *const c_void,
|
||||||
|
new_func: Option<CRYPTO_EX_new>,
|
||||||
|
dup_func: Option<CRYPTO_EX_dup>,
|
||||||
|
free_func: Option<CRYPTO_EX_free>)
|
||||||
|
-> c_int;
|
||||||
|
pub fn SSL_set_ex_data(ssl: *mut SSL, idx: c_int, data: *mut c_void) -> c_int;
|
||||||
|
pub fn SSL_get_ex_data(ssl: *mut SSL, idx: c_int) -> *mut c_void;
|
||||||
|
|
||||||
pub fn SSL_get_servername(ssl: *const SSL, name_type: c_long) -> *const c_char;
|
pub fn SSL_get_servername(ssl: *const SSL, name_type: c_long) -> *const c_char;
|
||||||
|
|
||||||
|
|
@ -751,6 +807,7 @@ extern "C" {
|
||||||
pub fn X509_sign(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int;
|
pub fn X509_sign(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int;
|
||||||
pub fn X509_get_pubkey(x: *mut X509) -> *mut EVP_PKEY;
|
pub fn X509_get_pubkey(x: *mut X509) -> *mut EVP_PKEY;
|
||||||
pub fn X509_to_X509_REQ(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> *mut X509_REQ;
|
pub fn X509_to_X509_REQ(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> *mut X509_REQ;
|
||||||
|
pub fn X509_get_ext_d2i(x: *mut X509, nid: c_int, crit: *mut c_int, idx: *mut c_int) -> *mut c_void;
|
||||||
|
|
||||||
pub fn X509_EXTENSION_free(ext: *mut X509_EXTENSION);
|
pub fn X509_EXTENSION_free(ext: *mut X509_EXTENSION);
|
||||||
|
|
||||||
|
|
@ -760,10 +817,13 @@ extern "C" {
|
||||||
pub fn X509_NAME_ENTRY_get_data(ne: *mut X509_NAME_ENTRY) -> *mut ASN1_STRING;
|
pub fn X509_NAME_ENTRY_get_data(ne: *mut X509_NAME_ENTRY) -> *mut ASN1_STRING;
|
||||||
|
|
||||||
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_char, s: *mut ASN1_STRING) -> c_int;
|
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_char, s: *mut ASN1_STRING) -> c_int;
|
||||||
|
pub fn ASN1_STRING_length(x: *mut ASN1_STRING) -> c_int;
|
||||||
|
pub fn ASN1_STRING_data(x: *mut ASN1_STRING) -> *mut c_uchar;
|
||||||
|
|
||||||
pub fn X509_STORE_CTX_get_current_cert(ct: *mut X509_STORE_CTX) -> *mut X509;
|
pub fn X509_STORE_CTX_get_current_cert(ct: *mut X509_STORE_CTX) -> *mut X509;
|
||||||
pub fn X509_STORE_CTX_get_error(ctx: *mut X509_STORE_CTX) -> c_int;
|
pub fn X509_STORE_CTX_get_error(ctx: *mut X509_STORE_CTX) -> c_int;
|
||||||
pub fn X509_STORE_CTX_get_ex_data(ctx: *mut X509_STORE_CTX, idx: c_int) -> *mut c_void;
|
pub fn X509_STORE_CTX_get_ex_data(ctx: *mut X509_STORE_CTX, idx: c_int) -> *mut c_void;
|
||||||
|
pub fn X509_STORE_CTX_get_error_depth(ctx: *mut X509_STORE_CTX) -> c_int;
|
||||||
|
|
||||||
pub fn X509V3_EXT_conf_nid(conf: *mut c_void, ctx: *mut X509V3_CTX, ext_nid: c_int, value: *mut c_char) -> *mut X509_EXTENSION;
|
pub fn X509V3_EXT_conf_nid(conf: *mut c_void, ctx: *mut X509V3_CTX, ext_nid: c_int, value: *mut c_char) -> *mut X509_EXTENSION;
|
||||||
pub fn X509V3_EXT_conf(conf: *mut c_void, ctx: *mut X509V3_CTX, name: *mut c_char, value: *mut c_char) -> *mut X509_EXTENSION;
|
pub fn X509V3_EXT_conf(conf: *mut c_void, ctx: *mut X509V3_CTX, name: *mut c_char, value: *mut c_char) -> *mut X509_EXTENSION;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
[package]
|
[package]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
version = "0.7.10"
|
version = "0.7.11"
|
||||||
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
description = "OpenSSL bindings"
|
description = "OpenSSL bindings"
|
||||||
repository = "https://github.com/sfackler/rust-openssl"
|
repository = "https://github.com/sfackler/rust-openssl"
|
||||||
documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.10/openssl"
|
documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.11/openssl"
|
||||||
readme = "../README.md"
|
readme = "../README.md"
|
||||||
keywords = ["crypto", "tls", "ssl", "dtls"]
|
keywords = ["crypto", "tls", "ssl", "dtls"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
@ -29,11 +29,11 @@ pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"]
|
||||||
nightly = []
|
nightly = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "0.4"
|
bitflags = ">= 0.5.0, < 0.7.0"
|
||||||
lazy_static = "0.2"
|
lazy_static = "0.2"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
openssl-sys = { version = "0.7.10", path = "../openssl-sys" }
|
openssl-sys = { version = "0.7.11", path = "../openssl-sys" }
|
||||||
openssl-sys-extras = { version = "0.7.10", path = "../openssl-sys-extras" }
|
openssl-sys-extras = { version = "0.7.11", path = "../openssl-sys-extras" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gcc = "0.3"
|
gcc = "0.3"
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,9 @@ pub enum Type {
|
||||||
AES_256_CFB128,
|
AES_256_CFB128,
|
||||||
AES_256_CFB8,
|
AES_256_CFB8,
|
||||||
|
|
||||||
|
DES_CBC,
|
||||||
|
DES_ECB,
|
||||||
|
|
||||||
RC4_128,
|
RC4_128,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -362,4 +365,26 @@ mod tests {
|
||||||
|
|
||||||
cipher_test(super::Type::AES_256_CFB8, pt, ct, key, iv);
|
cipher_test(super::Type::AES_256_CFB8, pt, ct, key, iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_des_cbc() {
|
||||||
|
|
||||||
|
let pt = "54686973206973206120746573742e";
|
||||||
|
let ct = "6f2867cfefda048a4046ef7e556c7132";
|
||||||
|
let key = "7cb66337f3d3c0fe";
|
||||||
|
let iv = "0001020304050607";
|
||||||
|
|
||||||
|
cipher_test(super::Type::DES_CBC, pt, ct, key, iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_des_ecb() {
|
||||||
|
|
||||||
|
let pt = "54686973206973206120746573742e";
|
||||||
|
let ct = "0050ab8aecec758843fe157b4dde938c";
|
||||||
|
let key = "7cb66337f3d3c0fe";
|
||||||
|
let iv = "0001020304050607";
|
||||||
|
|
||||||
|
cipher_test(super::Type::DES_ECB, pt, ct, key, iv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ pub fn evpc(t: symm::Type) -> (*const ffi::EVP_CIPHER, u32, u32) {
|
||||||
symm::Type::AES_256_CFB128 => (ffi::EVP_aes_256_cfb128(), 32, 16),
|
symm::Type::AES_256_CFB128 => (ffi::EVP_aes_256_cfb128(), 32, 16),
|
||||||
symm::Type::AES_256_CFB8 => (ffi::EVP_aes_256_cfb8(), 32, 16),
|
symm::Type::AES_256_CFB8 => (ffi::EVP_aes_256_cfb8(), 32, 16),
|
||||||
|
|
||||||
|
symm::Type::DES_CBC => (ffi::EVP_des_cbc(), 8, 8),
|
||||||
|
symm::Type::DES_ECB => (ffi::EVP_des_ecb(), 8, 8),
|
||||||
|
|
||||||
symm::Type::RC4_128 => (ffi::EVP_rc4(), 16, 0),
|
symm::Type::RC4_128 => (ffi::EVP_rc4(), 16, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.10")]
|
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.11")]
|
||||||
#![cfg_attr(feature = "nightly", feature(const_fn))]
|
#![cfg_attr(feature = "nightly", feature(const_fn))]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
||||||
|
|
@ -69,44 +69,44 @@ pub fn init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
flags SslContextOptions: u64 {
|
pub flags SslContextOptions: u64 {
|
||||||
const SSL_OP_MICROSOFT_SESS_ID_BUG = ffi_extras::SSL_OP_MICROSOFT_SESS_ID_BUG,
|
const SSL_OP_MICROSOFT_SESS_ID_BUG = ::ffi_extras::SSL_OP_MICROSOFT_SESS_ID_BUG,
|
||||||
const SSL_OP_NETSCAPE_CHALLENGE_BUG = ffi_extras::SSL_OP_NETSCAPE_CHALLENGE_BUG,
|
const SSL_OP_NETSCAPE_CHALLENGE_BUG = ::ffi_extras::SSL_OP_NETSCAPE_CHALLENGE_BUG,
|
||||||
const SSL_OP_LEGACY_SERVER_CONNECT = ffi_extras::SSL_OP_LEGACY_SERVER_CONNECT,
|
const SSL_OP_LEGACY_SERVER_CONNECT = ::ffi_extras::SSL_OP_LEGACY_SERVER_CONNECT,
|
||||||
const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = ffi_extras::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG,
|
const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = ::ffi_extras::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG,
|
||||||
const SSL_OP_TLSEXT_PADDING = ffi_extras::SSL_OP_TLSEXT_PADDING,
|
const SSL_OP_TLSEXT_PADDING = ::ffi_extras::SSL_OP_TLSEXT_PADDING,
|
||||||
const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = ffi_extras::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER,
|
const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = ::ffi_extras::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER,
|
||||||
const SSL_OP_SAFARI_ECDHE_ECDSA_BUG = ffi_extras::SSL_OP_SAFARI_ECDHE_ECDSA_BUG,
|
const SSL_OP_SAFARI_ECDHE_ECDSA_BUG = ::ffi_extras::SSL_OP_SAFARI_ECDHE_ECDSA_BUG,
|
||||||
const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = ffi_extras::SSL_OP_SSLEAY_080_CLIENT_DH_BUG,
|
const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = ::ffi_extras::SSL_OP_SSLEAY_080_CLIENT_DH_BUG,
|
||||||
const SSL_OP_TLS_D5_BUG = ffi_extras::SSL_OP_TLS_D5_BUG,
|
const SSL_OP_TLS_D5_BUG = ::ffi_extras::SSL_OP_TLS_D5_BUG,
|
||||||
const SSL_OP_TLS_BLOCK_PADDING_BUG = ffi_extras::SSL_OP_TLS_BLOCK_PADDING_BUG,
|
const SSL_OP_TLS_BLOCK_PADDING_BUG = ::ffi_extras::SSL_OP_TLS_BLOCK_PADDING_BUG,
|
||||||
const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = ffi_extras::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS,
|
const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = ::ffi_extras::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS,
|
||||||
const SSL_OP_NO_QUERY_MTU = ffi_extras::SSL_OP_NO_QUERY_MTU,
|
const SSL_OP_NO_QUERY_MTU = ::ffi_extras::SSL_OP_NO_QUERY_MTU,
|
||||||
const SSL_OP_COOKIE_EXCHANGE = ffi_extras::SSL_OP_COOKIE_EXCHANGE,
|
const SSL_OP_COOKIE_EXCHANGE = ::ffi_extras::SSL_OP_COOKIE_EXCHANGE,
|
||||||
const SSL_OP_NO_TICKET = ffi_extras::SSL_OP_NO_TICKET,
|
const SSL_OP_NO_TICKET = ::ffi_extras::SSL_OP_NO_TICKET,
|
||||||
const SSL_OP_CISCO_ANYCONNECT = ffi_extras::SSL_OP_CISCO_ANYCONNECT,
|
const SSL_OP_CISCO_ANYCONNECT = ::ffi_extras::SSL_OP_CISCO_ANYCONNECT,
|
||||||
const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = ffi_extras::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION,
|
const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = ::ffi_extras::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION,
|
||||||
const SSL_OP_NO_COMPRESSION = ffi_extras::SSL_OP_NO_COMPRESSION,
|
const SSL_OP_NO_COMPRESSION = ::ffi_extras::SSL_OP_NO_COMPRESSION,
|
||||||
const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = ffi_extras::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION,
|
const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = ::ffi_extras::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION,
|
||||||
const SSL_OP_SINGLE_ECDH_USE = ffi_extras::SSL_OP_SINGLE_ECDH_USE,
|
const SSL_OP_SINGLE_ECDH_USE = ::ffi_extras::SSL_OP_SINGLE_ECDH_USE,
|
||||||
const SSL_OP_SINGLE_DH_USE = ffi_extras::SSL_OP_SINGLE_DH_USE,
|
const SSL_OP_SINGLE_DH_USE = ::ffi_extras::SSL_OP_SINGLE_DH_USE,
|
||||||
const SSL_OP_CIPHER_SERVER_PREFERENCE = ffi_extras::SSL_OP_CIPHER_SERVER_PREFERENCE,
|
const SSL_OP_CIPHER_SERVER_PREFERENCE = ::ffi_extras::SSL_OP_CIPHER_SERVER_PREFERENCE,
|
||||||
const SSL_OP_TLS_ROLLBACK_BUG = ffi_extras::SSL_OP_TLS_ROLLBACK_BUG,
|
const SSL_OP_TLS_ROLLBACK_BUG = ::ffi_extras::SSL_OP_TLS_ROLLBACK_BUG,
|
||||||
const SSL_OP_NO_SSLV2 = ffi_extras::SSL_OP_NO_SSLv2,
|
const SSL_OP_NO_SSLV2 = ::ffi_extras::SSL_OP_NO_SSLv2,
|
||||||
const SSL_OP_NO_SSLV3 = ffi_extras::SSL_OP_NO_SSLv3,
|
const SSL_OP_NO_SSLV3 = ::ffi_extras::SSL_OP_NO_SSLv3,
|
||||||
const SSL_OP_NO_DTLSV1 = ffi_extras::SSL_OP_NO_DTLSv1,
|
const SSL_OP_NO_DTLSV1 = ::ffi_extras::SSL_OP_NO_DTLSv1,
|
||||||
const SSL_OP_NO_TLSV1 = ffi_extras::SSL_OP_NO_TLSv1,
|
const SSL_OP_NO_TLSV1 = ::ffi_extras::SSL_OP_NO_TLSv1,
|
||||||
const SSL_OP_NO_DTLSV1_2 = ffi_extras::SSL_OP_NO_DTLSv1_2,
|
const SSL_OP_NO_DTLSV1_2 = ::ffi_extras::SSL_OP_NO_DTLSv1_2,
|
||||||
const SSL_OP_NO_TLSV1_2 = ffi_extras::SSL_OP_NO_TLSv1_2,
|
const SSL_OP_NO_TLSV1_2 = ::ffi_extras::SSL_OP_NO_TLSv1_2,
|
||||||
const SSL_OP_NO_TLSV1_1 = ffi_extras::SSL_OP_NO_TLSv1_1,
|
const SSL_OP_NO_TLSV1_1 = ::ffi_extras::SSL_OP_NO_TLSv1_1,
|
||||||
const SSL_OP_NETSCAPE_CA_DN_BUG = ffi_extras::SSL_OP_NETSCAPE_CA_DN_BUG,
|
const SSL_OP_NETSCAPE_CA_DN_BUG = ::ffi_extras::SSL_OP_NETSCAPE_CA_DN_BUG,
|
||||||
const SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = ffi_extras::SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG,
|
const SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = ::ffi_extras::SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG,
|
||||||
const SSL_OP_CRYPTOPRO_TLSEXT_BUG = ffi_extras::SSL_OP_CRYPTOPRO_TLSEXT_BUG,
|
const SSL_OP_CRYPTOPRO_TLSEXT_BUG = ::ffi_extras::SSL_OP_CRYPTOPRO_TLSEXT_BUG,
|
||||||
const SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = ffi_extras::SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG,
|
const SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = ::ffi_extras::SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG,
|
||||||
const SSL_OP_MSIE_SSLV2_RSA_PADDING = ffi_extras::SSL_OP_MSIE_SSLV2_RSA_PADDING,
|
const SSL_OP_MSIE_SSLV2_RSA_PADDING = ::ffi_extras::SSL_OP_MSIE_SSLV2_RSA_PADDING,
|
||||||
const SSL_OP_PKCS1_CHECK_1 = ffi_extras::SSL_OP_PKCS1_CHECK_1,
|
const SSL_OP_PKCS1_CHECK_1 = ::ffi_extras::SSL_OP_PKCS1_CHECK_1,
|
||||||
const SSL_OP_PKCS1_CHECK_2 = ffi_extras::SSL_OP_PKCS1_CHECK_2,
|
const SSL_OP_PKCS1_CHECK_2 = ::ffi_extras::SSL_OP_PKCS1_CHECK_2,
|
||||||
const SSL_OP_EPHEMERAL_RSA = ffi_extras::SSL_OP_EPHEMERAL_RSA,
|
const SSL_OP_EPHEMERAL_RSA = ::ffi_extras::SSL_OP_EPHEMERAL_RSA,
|
||||||
const SSL_OP_ALL = SSL_OP_MICROSOFT_SESS_ID_BUG.bits|SSL_OP_NETSCAPE_CHALLENGE_BUG.bits
|
const SSL_OP_ALL = SSL_OP_MICROSOFT_SESS_ID_BUG.bits|SSL_OP_NETSCAPE_CHALLENGE_BUG.bits
|
||||||
|SSL_OP_LEGACY_SERVER_CONNECT.bits|SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG.bits
|
|SSL_OP_LEGACY_SERVER_CONNECT.bits|SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG.bits
|
||||||
|SSL_OP_TLSEXT_PADDING.bits|SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER.bits
|
|SSL_OP_TLSEXT_PADDING.bits|SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER.bits
|
||||||
|
|
@ -214,19 +214,20 @@ impl SslMethod {
|
||||||
|
|
||||||
/// Determines the type of certificate verification used
|
/// Determines the type of certificate verification used
|
||||||
bitflags! {
|
bitflags! {
|
||||||
flags SslVerifyMode: i32 {
|
pub flags SslVerifyMode: i32 {
|
||||||
/// Verify that the server's certificate is trusted
|
/// Verify that the server's certificate is trusted
|
||||||
const SSL_VERIFY_PEER = ffi::SSL_VERIFY_PEER,
|
const SSL_VERIFY_PEER = ::ffi::SSL_VERIFY_PEER,
|
||||||
/// Do not verify the server's certificate
|
/// Do not verify the server's certificate
|
||||||
const SSL_VERIFY_NONE = ffi::SSL_VERIFY_NONE,
|
const SSL_VERIFY_NONE = ::ffi::SSL_VERIFY_NONE,
|
||||||
/// Terminate handshake if client did not return a certificate.
|
/// Terminate handshake if client did not return a certificate.
|
||||||
/// Use together with SSL_VERIFY_PEER.
|
/// Use together with SSL_VERIFY_PEER.
|
||||||
const SSL_VERIFY_FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
|
const SSL_VERIFY_FAIL_IF_NO_PEER_CERT = ::ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref INDEXES: Mutex<HashMap<TypeId, c_int>> = Mutex::new(HashMap::new());
|
static ref INDEXES: Mutex<HashMap<TypeId, c_int>> = Mutex::new(HashMap::new());
|
||||||
|
static ref SSL_INDEXES: Mutex<HashMap<TypeId, c_int>> = Mutex::new(HashMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a static index for user data of type T
|
// Creates a static index for user data of type T
|
||||||
|
|
@ -236,6 +237,10 @@ fn get_verify_data_idx<T: Any + 'static>() -> c_int {
|
||||||
*INDEXES.lock().unwrap().entry(TypeId::of::<T>()).or_insert_with(|| get_new_idx::<T>())
|
*INDEXES.lock().unwrap().entry(TypeId::of::<T>()).or_insert_with(|| get_new_idx::<T>())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_ssl_verify_data_idx<T: Any + 'static>() -> c_int {
|
||||||
|
*SSL_INDEXES.lock().unwrap().entry(TypeId::of::<T>()).or_insert_with(|| get_new_ssl_idx::<T>())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "npn")]
|
#[cfg(feature = "npn")]
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref NPN_PROTOS_IDX: c_int = get_new_idx::<Vec<u8>>();
|
static ref NPN_PROTOS_IDX: c_int = get_new_idx::<Vec<u8>>();
|
||||||
|
|
@ -267,6 +272,26 @@ fn get_new_idx<T>() -> c_int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_new_ssl_idx<T>() -> c_int {
|
||||||
|
extern "C" fn free_data_box<T>(_parent: *mut c_void,
|
||||||
|
ptr: *mut c_void,
|
||||||
|
_ad: *mut ffi::CRYPTO_EX_DATA,
|
||||||
|
_idx: c_int,
|
||||||
|
_argl: c_long,
|
||||||
|
_argp: *mut c_void) {
|
||||||
|
if !ptr.is_null() {
|
||||||
|
let _: Box<T> = unsafe { mem::transmute(ptr) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let f: ffi::CRYPTO_EX_free = free_data_box::<T>;
|
||||||
|
let idx = ffi::SSL_get_ex_new_index(0, ptr::null(), None, None, Some(f));
|
||||||
|
assert!(idx >= 0);
|
||||||
|
idx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int {
|
extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int {
|
||||||
unsafe {
|
unsafe {
|
||||||
let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx();
|
let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx();
|
||||||
|
|
@ -311,6 +336,21 @@ extern "C" fn raw_verify_with_data<T>(preverify_ok: c_int,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn ssl_raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int
|
||||||
|
where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx();
|
||||||
|
let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx);
|
||||||
|
let verify = ffi::SSL_get_ex_data(ssl, get_ssl_verify_data_idx::<F>());
|
||||||
|
let verify: &F = mem::transmute(verify);
|
||||||
|
|
||||||
|
let ctx = X509StoreContext::new(x509_ctx);
|
||||||
|
|
||||||
|
verify(preverify_ok != 0, &ctx) as c_int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" fn raw_sni(ssl: *mut ffi::SSL, ad: &mut c_int, _arg: *mut c_void) -> c_int {
|
extern "C" fn raw_sni(ssl: *mut ffi::SSL, ad: &mut c_int, _arg: *mut c_void) -> c_int {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl);
|
let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl);
|
||||||
|
|
@ -928,6 +968,30 @@ impl Ssl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the verification mode to be used during the handshake process.
|
||||||
|
///
|
||||||
|
/// Use `set_verify_callback` to additionally add a callback.
|
||||||
|
pub fn set_verify(&mut self, mode: SslVerifyMode) {
|
||||||
|
unsafe { ffi::SSL_set_verify(self.ssl, mode.bits as c_int, None) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the certificate verification callback to be used during the
|
||||||
|
/// handshake process.
|
||||||
|
///
|
||||||
|
/// The callback is provided with a boolean indicating if the
|
||||||
|
/// preveification process was successful, and an object providing access
|
||||||
|
/// to the certificate chain. It should return `true` if the certificate
|
||||||
|
/// chain is valid and `false` otherwise.
|
||||||
|
pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
|
||||||
|
where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
let verify = Box::new(verify);
|
||||||
|
ffi::SSL_set_ex_data(self.ssl, get_ssl_verify_data_idx::<F>(), mem::transmute(verify));
|
||||||
|
ffi::SSL_set_verify(self.ssl, mode.bits as c_int, Some(ssl_raw_verify::<F>));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_current_cipher<'a>(&'a self) -> Option<SslCipher<'a>> {
|
pub fn get_current_cipher<'a>(&'a self) -> Option<SslCipher<'a>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = ffi::SSL_get_current_cipher(self.ssl);
|
let ptr = ffi::SSL_get_current_cipher(self.ssl);
|
||||||
|
|
|
||||||
|
|
@ -381,6 +381,36 @@ run_test!(verify_callback_data, |method, stream| {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
run_test!(ssl_verify_callback, |method, stream| {
|
||||||
|
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||||
|
use ssl::IntoSsl;
|
||||||
|
|
||||||
|
static CHECKED: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||||
|
|
||||||
|
let ctx = SslContext::new(method).unwrap();
|
||||||
|
let mut ssl = ctx.into_ssl().unwrap();
|
||||||
|
|
||||||
|
let node_hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b";
|
||||||
|
let node_id = node_hash_str.from_hex().unwrap();
|
||||||
|
ssl.set_verify_callback(SSL_VERIFY_PEER, move |_, x509| {
|
||||||
|
CHECKED.store(1, Ordering::SeqCst);
|
||||||
|
match x509.get_current_cert() {
|
||||||
|
None => false,
|
||||||
|
Some(cert) => {
|
||||||
|
let fingerprint = cert.fingerprint(SHA256).unwrap();
|
||||||
|
fingerprint == node_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
match SslStream::connect_generic(ssl, stream) {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(err) => panic!("Expected success, got {:?}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(CHECKED.load(Ordering::SeqCst), 1);
|
||||||
|
});
|
||||||
|
|
||||||
// Make sure every write call translates to a write call to the underlying socket.
|
// Make sure every write call translates to a write call to the underlying socket.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_write_hits_stream() {
|
fn test_write_hits_stream() {
|
||||||
|
|
@ -1061,6 +1091,7 @@ fn refcount_ssl_context() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg_attr(windows, ignore)] // don't have a trusted CA list easily available :(
|
||||||
fn default_verify_paths() {
|
fn default_verify_paths() {
|
||||||
let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap();
|
let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||||
ctx.set_default_verify_paths().unwrap();
|
ctx.set_default_verify_paths().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use nid::Nid;
|
use nid::Nid;
|
||||||
|
|
||||||
/// Type-only version of the `Extension` enum.
|
/// Type-only version of the `Extension` enum.
|
||||||
|
|
@ -79,7 +80,7 @@ impl ExtensionType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_name<'a>(&'a self) -> Option<&'a str> {
|
pub fn get_name(&self) -> Option<&str> {
|
||||||
match self {
|
match self {
|
||||||
&ExtensionType::OtherStr(ref s) => Some(s),
|
&ExtensionType::OtherStr(ref s) => Some(s),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,16 @@ use libc::{c_char, c_int, c_long, c_ulong, c_uint, c_void};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::ffi::{CString, CStr};
|
use std::ffi::CString;
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
use std::slice;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use asn1::Asn1Time;
|
use asn1::Asn1Time;
|
||||||
use bio::MemBio;
|
use bio::MemBio;
|
||||||
|
|
@ -20,7 +22,7 @@ use crypto::rand::rand_bytes;
|
||||||
use ffi;
|
use ffi;
|
||||||
use ffi_extras;
|
use ffi_extras;
|
||||||
use ssl::error::{SslError, StreamError};
|
use ssl::error::{SslError, StreamError};
|
||||||
use nid;
|
use nid::Nid;
|
||||||
|
|
||||||
pub mod extension;
|
pub mod extension;
|
||||||
|
|
||||||
|
|
@ -29,14 +31,12 @@ use self::extension::{ExtensionType, Extension};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub struct SslString {
|
pub struct SslString(&'static str);
|
||||||
s: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s> Drop for SslString {
|
impl<'s> Drop for SslString {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::CRYPTO_free(self.s.as_ptr() as *mut c_void);
|
ffi::CRYPTO_free(self.0.as_ptr() as *mut c_void);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -45,25 +45,26 @@ impl Deref for SslString {
|
||||||
type Target = str;
|
type Target = str;
|
||||||
|
|
||||||
fn deref(&self) -> &str {
|
fn deref(&self) -> &str {
|
||||||
self.s
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SslString {
|
impl SslString {
|
||||||
unsafe fn new(buf: *const c_char) -> SslString {
|
unsafe fn new(buf: *const c_char, len: c_int) -> SslString {
|
||||||
SslString { s: str::from_utf8(CStr::from_ptr(buf as *const _).to_bytes()).unwrap() }
|
let slice = slice::from_raw_parts(buf as *const _, len as usize);
|
||||||
|
SslString(str::from_utf8_unchecked(slice))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SslString {
|
impl fmt::Display for SslString {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Display::fmt(self.s, f)
|
fmt::Display::fmt(self.0, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for SslString {
|
impl fmt::Debug for SslString {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Debug::fmt(self.s, f)
|
fmt::Debug::fmt(self.0, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,6 +104,10 @@ impl X509StoreContext {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn error_depth(&self) -> u32 {
|
||||||
|
unsafe { ffi::X509_STORE_CTX_get_error_depth(self.ctx) as u32 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
|
@ -464,6 +469,24 @@ impl<'ctx> X509<'ctx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns this certificate's SAN entries, if they exist.
|
||||||
|
pub fn subject_alt_names<'a>(&'a self) -> Option<GeneralNames<'a>> {
|
||||||
|
unsafe {
|
||||||
|
let stack = ffi::X509_get_ext_d2i(self.handle,
|
||||||
|
Nid::SubjectAltName as c_int,
|
||||||
|
ptr::null_mut(),
|
||||||
|
ptr::null_mut());
|
||||||
|
if stack.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(GeneralNames {
|
||||||
|
stack: stack as *const _,
|
||||||
|
m: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn public_key(&self) -> PKey {
|
pub fn public_key(&self) -> PKey {
|
||||||
let pkey = unsafe { ffi::X509_get_pubkey(self.handle) };
|
let pkey = unsafe { ffi::X509_get_pubkey(self.handle) };
|
||||||
assert!(!pkey.is_null());
|
assert!(!pkey.is_null());
|
||||||
|
|
@ -544,7 +567,7 @@ pub struct X509NameEntry<'x> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'x> X509Name<'x> {
|
impl<'x> X509Name<'x> {
|
||||||
pub fn text_by_nid(&self, nid: nid::Nid) -> Option<SslString> {
|
pub fn text_by_nid(&self, nid: Nid) -> Option<SslString> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let loc = ffi::X509_NAME_get_index_by_NID(self.name, nid as c_int, -1);
|
let loc = ffi::X509_NAME_get_index_by_NID(self.name, nid as c_int, -1);
|
||||||
if loc == -1 {
|
if loc == -1 {
|
||||||
|
|
@ -570,7 +593,7 @@ impl<'x> X509Name<'x> {
|
||||||
|
|
||||||
assert!(!str_from_asn1.is_null());
|
assert!(!str_from_asn1.is_null());
|
||||||
|
|
||||||
Some(SslString::new(str_from_asn1))
|
Some(SslString::new(str_from_asn1, len))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -766,6 +789,120 @@ make_validation_error!(X509_V_OK,
|
||||||
X509ApplicationVerification = X509_V_ERR_APPLICATION_VERIFICATION,
|
X509ApplicationVerification = X509_V_ERR_APPLICATION_VERIFICATION,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// A collection of OpenSSL `GENERAL_NAME`s.
|
||||||
|
pub struct GeneralNames<'a> {
|
||||||
|
stack: *const ffi::stack_st_GENERAL_NAME,
|
||||||
|
m: PhantomData<&'a ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> GeneralNames<'a> {
|
||||||
|
/// Returns the number of `GeneralName`s in this structure.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
unsafe {
|
||||||
|
(*self.stack).stack.num as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the specified `GeneralName`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `idx` is not less than `len()`.
|
||||||
|
pub fn get(&self, idx: usize) -> GeneralName<'a> {
|
||||||
|
unsafe {
|
||||||
|
assert!(idx < self.len());
|
||||||
|
|
||||||
|
GeneralName {
|
||||||
|
name: *(*self.stack).stack.data.offset(idx as isize) as *const ffi::GENERAL_NAME,
|
||||||
|
m: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over the `GeneralName`s in this structure.
|
||||||
|
pub fn iter(&self) -> GeneralNamesIter {
|
||||||
|
GeneralNamesIter {
|
||||||
|
names: self,
|
||||||
|
idx: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a GeneralNames<'a> {
|
||||||
|
type Item = GeneralName<'a>;
|
||||||
|
type IntoIter = GeneralNamesIter<'a>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> GeneralNamesIter<'a> {
|
||||||
|
self.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An iterator over OpenSSL `GENERAL_NAME`s.
|
||||||
|
pub struct GeneralNamesIter<'a> {
|
||||||
|
names: &'a GeneralNames<'a>,
|
||||||
|
idx: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for GeneralNamesIter<'a> {
|
||||||
|
type Item = GeneralName<'a>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.idx < self.names.len() {
|
||||||
|
let name = self.names.get(self.idx);
|
||||||
|
self.idx += 1;
|
||||||
|
Some(name)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
let size = self.names.len() - self.idx;
|
||||||
|
(size, Some(size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ExactSizeIterator for GeneralNamesIter<'a> {}
|
||||||
|
|
||||||
|
/// An OpenSSL `GENERAL_NAME`.
|
||||||
|
pub struct GeneralName<'a> {
|
||||||
|
name: *const ffi::GENERAL_NAME,
|
||||||
|
m: PhantomData<&'a ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> GeneralName<'a> {
|
||||||
|
/// Returns the contents of this `GeneralName` if it is a `dNSName`.
|
||||||
|
pub fn dnsname(&self) -> Option<&str> {
|
||||||
|
unsafe {
|
||||||
|
if (*self.name).type_ != ffi::GEN_DNS {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _);
|
||||||
|
let len = ffi::ASN1_STRING_length((*self.name).d as *mut _);
|
||||||
|
|
||||||
|
let slice = slice::from_raw_parts(ptr as *const u8, len as usize);
|
||||||
|
// dNSNames are stated to be ASCII (specifically IA5). Hopefully
|
||||||
|
// OpenSSL checks that when loading a certificate but if not we'll
|
||||||
|
// use this instead of from_utf8_unchecked just in case.
|
||||||
|
str::from_utf8(slice).ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the contents of this `GeneralName` if it is an `iPAddress`.
|
||||||
|
pub fn ipaddress(&self) -> Option<&[u8]> {
|
||||||
|
unsafe {
|
||||||
|
if (*self.name).type_ != ffi::GEN_IPADD {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _);
|
||||||
|
let len = ffi::ASN1_STRING_length((*self.name).d as *mut _);
|
||||||
|
|
||||||
|
Some(slice::from_raw_parts(ptr as *const u8, len as usize))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_negative_serial() {
|
fn test_negative_serial() {
|
||||||
|
|
|
||||||
|
|
@ -157,3 +157,30 @@ fn test_nid_uid_value() {
|
||||||
};
|
};
|
||||||
assert_eq!(&cn as &str, "this is the userId");
|
assert_eq!(&cn as &str, "this is the userId");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_subject_alt_name() {
|
||||||
|
let mut file = File::open("test/alt_name_cert.pem").unwrap();
|
||||||
|
let cert = X509::from_pem(&mut file).unwrap();
|
||||||
|
|
||||||
|
let subject_alt_names = cert.subject_alt_names().unwrap();
|
||||||
|
assert_eq!(3, subject_alt_names.len());
|
||||||
|
assert_eq!(Some("foobar.com"), subject_alt_names.get(0).dnsname());
|
||||||
|
assert_eq!(subject_alt_names.get(1).ipaddress(), Some(&[127, 0, 0, 1][..]));
|
||||||
|
assert_eq!(subject_alt_names.get(2).ipaddress(),
|
||||||
|
Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_subject_alt_name_iter() {
|
||||||
|
let mut file = File::open("test/alt_name_cert.pem").unwrap();
|
||||||
|
let cert = X509::from_pem(&mut file).unwrap();
|
||||||
|
|
||||||
|
let subject_alt_names = cert.subject_alt_names().unwrap();
|
||||||
|
let mut subject_alt_names_iter = subject_alt_names.iter();
|
||||||
|
assert_eq!(subject_alt_names_iter.next().unwrap().dnsname(), Some("foobar.com"));
|
||||||
|
assert_eq!(subject_alt_names_iter.next().unwrap().ipaddress(), Some(&[127, 0, 0, 1][..]));
|
||||||
|
assert_eq!(subject_alt_names_iter.next().unwrap().ipaddress(),
|
||||||
|
Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..]));
|
||||||
|
assert!(subject_alt_names_iter.next().is_none());
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEOjCCAyKgAwIBAgIJAJz42fzGUJGeMA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNV
|
||||||
|
BAYTAlVTMQswCQYDVQQIDAJOWTERMA8GA1UEBwwITmV3IFlvcmsxFTATBgNVBAoM
|
||||||
|
DEV4YW1wbGUsIExMQzEYMBYGA1UEAwwPRXhhbXBsZSBDb21wYW55MR8wHQYJKoZI
|
||||||
|
hvcNAQkBFhB0ZXN0QGV4YW1wbGUuY29tMB4XDTE2MDQzMDA0MDg1NloXDTE3MDQz
|
||||||
|
MDA0MDg1NlowfzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMREwDwYDVQQHDAhO
|
||||||
|
ZXcgWW9yazEVMBMGA1UECgwMRXhhbXBsZSwgTExDMRgwFgYDVQQDDA9FeGFtcGxl
|
||||||
|
IENvbXBhbnkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wggEiMA0G
|
||||||
|
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDggl2TbtO5Ewi/q8kV56xK6HBpwsj9
|
||||||
|
wBoqGi6hkKm/8lhLTkuUG6WbEUepi7n9d7tjI9hwYN7MKtppAnS+d+Zh6sKMgLJn
|
||||||
|
hONkbQBJkYWwuIxRVXORCdyZDNzXP1rlb6ynmj6mItuPTRVNNMaZP+24fgXtwGk8
|
||||||
|
P2nqA1ONbmyaP27txV+Rd8fmQvW3vSmq7iDob661TOtLZRqqVRpnLDGpLXTCptYz
|
||||||
|
dLN1nDWKjBUFpPGDxvfcSE3Yf9LaQM2uDHRygSgTFusbwarAGrAk8krsm/Tiaumx
|
||||||
|
Ls74MY6OEoLnPbEi5epWLqPmoE1nxrvYLtaWh3TTET3H72yL0+1PZTkpAgMBAAGj
|
||||||
|
gbgwgbUwHQYDVR0OBBYEFAIcHhTPUqVdK85u47vo8z0viJGPMB8GA1UdIwQYMBaA
|
||||||
|
FAIcHhTPUqVdK85u47vo8z0viJGPMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMC0G
|
||||||
|
A1UdEQQmMCSCCmZvb2Jhci5jb22HBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwLAYJ
|
||||||
|
YIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMA0GCSqG
|
||||||
|
SIb3DQEBCwUAA4IBAQDeYsuJaxbnxR2wDRSbxMpPp2b6fHPxC1vArKTSrQ/X+5s7
|
||||||
|
YcQ29jkzD8FbET8iPsCOn/IECBiDKOpckkO6dBWM05ma9HHzWjQOJ7Lo6gEsvk4d
|
||||||
|
+M/jJz5IaJ7hOxp1hGqwNQ+PJQOZMmlruNcOzPU36qaWJ03+NYOKar5VpIrRxCNc
|
||||||
|
uehTArmJqDLQPfgETEhMYfpkqf3s/cGb1uyeCpzgIRPpf4Ki1Oys5cV/BqIn7n5g
|
||||||
|
7sUrhXboYL4+eYt5V4rcc4rLI5J5IP/a1Z+Z6UVH+Mbiyl0iD8aRr/bo9WvKih3C
|
||||||
|
2LBO0Apl0tkXUOMWp7G0UYHVEndwPjZnVoM42f11
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
@ -15,7 +15,7 @@ fi
|
||||||
|
|
||||||
mkdir /tmp/openssl
|
mkdir /tmp/openssl
|
||||||
cd /tmp/openssl
|
cd /tmp/openssl
|
||||||
curl https://openssl.org/source/openssl-1.0.2g.tar.gz | tar --strip-components=1 -xzf -
|
curl https://openssl.org/source/openssl-1.0.2h.tar.gz | tar --strip-components=1 -xzf -
|
||||||
./Configure --prefix=$HOME/openssl shared --cross-compile-prefix=$CROSS $OS_COMPILER
|
./Configure --prefix=$HOME/openssl shared --cross-compile-prefix=$CROSS $OS_COMPILER
|
||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue