Merge branch 'release-v0.7.11' into release

This commit is contained in:
Steven Fackler 2016-05-05 13:32:41 -07:00
commit 4294511f2b
19 changed files with 452 additions and 106 deletions

View File

@ -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

View File

@ -2,7 +2,7 @@
[![Build Status](https://travis-ci.org/sfackler/rust-openssl.svg?branch=master)](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

View File

@ -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

View File

@ -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"

View File

@ -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;

View File

@ -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)

View File

@ -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"

View File

@ -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;

View File

@ -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"

View File

@ -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);
}
}

View File

@ -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),
}
}

View File

@ -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]

View File

@ -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);

View File

@ -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();

View File

@ -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,

View File

@ -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() {

View File

@ -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());
}

View File

@ -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-----

View File

@ -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