Merge branch 'release-v0.7.11' into release
This commit is contained in:
commit
4294511f2b
|
|
@ -6,8 +6,7 @@ addons:
|
|||
- gcc-arm-linux-gnueabihf
|
||||
rust:
|
||||
- nightly
|
||||
- beta
|
||||
- 1.4.0
|
||||
- 1.8.0
|
||||
os:
|
||||
- osx
|
||||
- linux
|
||||
|
|
@ -19,7 +18,7 @@ matrix:
|
|||
# include:
|
||||
# - os: linux
|
||||
# env: TARGET=arm-unknown-linux-gnueabihf TEST_FEATURES=true
|
||||
# rust: 1.4.0
|
||||
# rust: 1.8.0
|
||||
exclude:
|
||||
- os: osx
|
||||
env: TEST_FEATURES=true
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[](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
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ environment:
|
|||
# - TARGET: x86_64-pc-windows-msvc
|
||||
# BITS: 64
|
||||
install:
|
||||
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2g.exe"
|
||||
- Win%BITS%OpenSSL-1_0_2g.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
|
||||
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.5.0-${env:TARGET}.exe"
|
||||
- rust-1.5.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
|
||||
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2h.exe"
|
||||
- Win%BITS%OpenSSL-1_0_2h.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
|
||||
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.8.0-${env:TARGET}.exe"
|
||||
- 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:\MinGW\bin
|
||||
- rustc -V
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
[package]
|
||||
name = "openssl-sys-extras"
|
||||
version = "0.7.10"
|
||||
version = "0.7.11"
|
||||
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
||||
license = "MIT"
|
||||
description = "Extra FFI bindings to OpenSSL that require a C shim"
|
||||
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"
|
||||
|
||||
[features]
|
||||
|
|
@ -13,7 +13,7 @@ ecdh_auto = []
|
|||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
openssl-sys = { version = "0.7.10", path = "../openssl-sys" }
|
||||
openssl-sys = { version = "0.7.11", path = "../openssl-sys" }
|
||||
|
||||
[build-dependencies]
|
||||
gcc = "0.3"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#![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 libc;
|
||||
|
|
|
|||
|
|
@ -3,32 +3,6 @@
|
|||
#include <openssl/dh.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
|
||||
// Copied from openssl crypto/hmac/hmac.c
|
||||
int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
[package]
|
||||
name = "openssl-sys"
|
||||
version = "0.7.10"
|
||||
version = "0.7.11"
|
||||
authors = ["Alex Crichton <alex@alexcrichton.com>",
|
||||
"Steven Fackler <sfackler@gmail.com>"]
|
||||
license = "MIT"
|
||||
description = "FFI bindings to 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"
|
||||
build = "build.rs"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]
|
||||
#![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;
|
||||
|
||||
|
|
@ -34,10 +34,23 @@ pub type X509_NAME = c_void;
|
|||
pub type X509_NAME_ENTRY = c_void;
|
||||
pub type X509_REQ = 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;
|
||||
|
||||
#[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,
|
||||
c_int,
|
||||
*const c_char,
|
||||
|
|
@ -63,6 +76,15 @@ pub struct BIO_METHOD {
|
|||
// so we can create static BIO_METHODs
|
||||
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)]
|
||||
pub struct RSA {
|
||||
pub pad: c_int,
|
||||
|
|
@ -178,6 +200,17 @@ pub struct X509V3_CTX {
|
|||
// 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 Clone for X509V3_CTX {
|
||||
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_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 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_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,
|
||||
salt: *const u8, data: *const u8, datalen: 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_state_string(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;
|
||||
|
||||
|
|
@ -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_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_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);
|
||||
|
||||
|
|
@ -760,10 +817,13 @@ extern "C" {
|
|||
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_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_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_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(conf: *mut c_void, ctx: *mut X509V3_CTX, name: *mut c_char, value: *mut c_char) -> *mut X509_EXTENSION;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
[package]
|
||||
name = "openssl"
|
||||
version = "0.7.10"
|
||||
version = "0.7.11"
|
||||
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
||||
license = "Apache-2.0"
|
||||
description = "OpenSSL bindings"
|
||||
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"
|
||||
keywords = ["crypto", "tls", "ssl", "dtls"]
|
||||
build = "build.rs"
|
||||
|
|
@ -29,11 +29,11 @@ pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"]
|
|||
nightly = []
|
||||
|
||||
[dependencies]
|
||||
bitflags = "0.4"
|
||||
bitflags = ">= 0.5.0, < 0.7.0"
|
||||
lazy_static = "0.2"
|
||||
libc = "0.2"
|
||||
openssl-sys = { version = "0.7.10", path = "../openssl-sys" }
|
||||
openssl-sys-extras = { version = "0.7.10", path = "../openssl-sys-extras" }
|
||||
openssl-sys = { version = "0.7.11", path = "../openssl-sys" }
|
||||
openssl-sys-extras = { version = "0.7.11", path = "../openssl-sys-extras" }
|
||||
|
||||
[build-dependencies]
|
||||
gcc = "0.3"
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ pub enum Type {
|
|||
AES_256_CFB128,
|
||||
AES_256_CFB8,
|
||||
|
||||
DES_CBC,
|
||||
DES_ECB,
|
||||
|
||||
RC4_128,
|
||||
}
|
||||
|
||||
|
|
@ -362,4 +365,26 @@ mod tests {
|
|||
|
||||
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_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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))]
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
|||
|
|
@ -69,44 +69,44 @@ pub fn init() {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
flags SslContextOptions: u64 {
|
||||
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_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_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_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_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_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_COOKIE_EXCHANGE = ffi_extras::SSL_OP_COOKIE_EXCHANGE,
|
||||
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_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_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_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_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_SSLV3 = ffi_extras::SSL_OP_NO_SSLv3,
|
||||
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_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_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_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_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_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_EPHEMERAL_RSA = ffi_extras::SSL_OP_EPHEMERAL_RSA,
|
||||
pub flags SslContextOptions: u64 {
|
||||
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_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_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_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_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_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_COOKIE_EXCHANGE = ::ffi_extras::SSL_OP_COOKIE_EXCHANGE,
|
||||
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_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_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_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_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_SSLV3 = ::ffi_extras::SSL_OP_NO_SSLv3,
|
||||
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_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_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_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_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_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_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
|
||||
|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
|
||||
|
|
@ -214,19 +214,20 @@ impl SslMethod {
|
|||
|
||||
/// Determines the type of certificate verification used
|
||||
bitflags! {
|
||||
flags SslVerifyMode: i32 {
|
||||
pub flags SslVerifyMode: i32 {
|
||||
/// 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
|
||||
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.
|
||||
/// 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! {
|
||||
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
|
||||
|
|
@ -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>())
|
||||
}
|
||||
|
||||
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")]
|
||||
lazy_static! {
|
||||
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 {
|
||||
unsafe {
|
||||
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 {
|
||||
unsafe {
|
||||
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>> {
|
||||
unsafe {
|
||||
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.
|
||||
#[test]
|
||||
fn test_write_hits_stream() {
|
||||
|
|
@ -1061,6 +1091,7 @@ fn refcount_ssl_context() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(windows, ignore)] // don't have a trusted CA list easily available :(
|
||||
fn default_verify_paths() {
|
||||
let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||
ctx.set_default_verify_paths().unwrap();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use std::fmt;
|
||||
|
||||
use nid::Nid;
|
||||
|
||||
/// 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 {
|
||||
&ExtensionType::OtherStr(ref s) => Some(s),
|
||||
_ => 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::prelude::*;
|
||||
use std::cmp::Ordering;
|
||||
use std::ffi::{CString, CStr};
|
||||
use std::ffi::CString;
|
||||
use std::iter::repeat;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::ops::Deref;
|
||||
use std::fmt;
|
||||
use std::str;
|
||||
use std::slice;
|
||||
use std::collections::HashMap;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use asn1::Asn1Time;
|
||||
use bio::MemBio;
|
||||
|
|
@ -20,7 +22,7 @@ use crypto::rand::rand_bytes;
|
|||
use ffi;
|
||||
use ffi_extras;
|
||||
use ssl::error::{SslError, StreamError};
|
||||
use nid;
|
||||
use nid::Nid;
|
||||
|
||||
pub mod extension;
|
||||
|
||||
|
|
@ -29,14 +31,12 @@ use self::extension::{ExtensionType, Extension};
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub struct SslString {
|
||||
s: &'static str,
|
||||
}
|
||||
pub struct SslString(&'static str);
|
||||
|
||||
impl<'s> Drop for SslString {
|
||||
fn drop(&mut self) {
|
||||
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;
|
||||
|
||||
fn deref(&self) -> &str {
|
||||
self.s
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl SslString {
|
||||
unsafe fn new(buf: *const c_char) -> SslString {
|
||||
SslString { s: str::from_utf8(CStr::from_ptr(buf as *const _).to_bytes()).unwrap() }
|
||||
unsafe fn new(buf: *const c_char, len: c_int) -> SslString {
|
||||
let slice = slice::from_raw_parts(buf as *const _, len as usize);
|
||||
SslString(str::from_utf8_unchecked(slice))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for SslString {
|
||||
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 {
|
||||
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)]
|
||||
|
|
@ -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 {
|
||||
let pkey = unsafe { ffi::X509_get_pubkey(self.handle) };
|
||||
assert!(!pkey.is_null());
|
||||
|
|
@ -544,7 +567,7 @@ pub struct X509NameEntry<'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 {
|
||||
let loc = ffi::X509_NAME_get_index_by_NID(self.name, nid as c_int, -1);
|
||||
if loc == -1 {
|
||||
|
|
@ -570,7 +593,7 @@ impl<'x> X509Name<'x> {
|
|||
|
||||
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,
|
||||
);
|
||||
|
||||
/// 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]
|
||||
fn test_negative_serial() {
|
||||
|
|
|
|||
|
|
@ -157,3 +157,30 @@ fn test_nid_uid_value() {
|
|||
};
|
||||
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
|
||||
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
|
||||
make
|
||||
make install
|
||||
|
|
|
|||
Loading…
Reference in New Issue