Commit 0cb4368e authored by Steven Fackler's avatar Steven Fackler
Browse files

Merge pull request #221 from jethrogb/topic/ssl_options

Several SSL option fixes
parents 32292961 6a725acf
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
@@ -2,7 +2,10 @@ extern crate pkg_config;
extern crate gcc;

use std::env;
use std::fmt::Write as FmtWrite;
use std::path::PathBuf;
use std::fs::File;
use std::io::Write;

fn main() {
    let target = env::var("TARGET").unwrap();
@@ -65,7 +68,63 @@ fn main() {
    build_openssl_shim(&include_dirs);
}

macro_rules! import_options {
    ( $( $name:ident $val:expr  )* ) => {
       &[ $( (stringify!($name),$val), )* ]
    };
}

fn generate_options_shim() -> PathBuf {
    let options: &[(&'static str,u64)]=include!("src/ssl_options.rs");
    let mut shim = String::new();
    writeln!(shim,"#include <stdint.h>").unwrap();
    writeln!(shim,"#include <openssl/ssl.h>").unwrap();

    for &(name,value) in options {
        writeln!(shim,"#define RUST_{} UINT64_C({})",name,value).unwrap();
        writeln!(shim,"#ifndef {}",name).unwrap();
        writeln!(shim,"# define {} 0",name).unwrap();
        writeln!(shim,"#endif").unwrap();
    }

    writeln!(shim,"#define COPY_MASK ( \\").unwrap();

    let mut it=options.iter().peekable();
    while let Some(&(name,_))=it.next()  {
        let eol=match it.peek() {
            Some(_) => " | \\",
            None    => " )"
        };
        writeln!(shim,"    ((RUST_{0}==(uint64_t)(uint32_t){0})?RUST_{0}:UINT64_C(0)){1}",name,eol).unwrap();
    }

    writeln!(shim,"long rust_openssl_ssl_ctx_options_rust_to_c(uint64_t rustval) {{").unwrap();
    writeln!(shim,"    long cval=rustval&COPY_MASK;").unwrap();
    for &(name,_) in options {
        writeln!(shim,"    if (rustval&RUST_{0}) cval|={0};",name).unwrap();
    }
    writeln!(shim,"    return cval;").unwrap();
    writeln!(shim,"}}").unwrap();

    writeln!(shim,"uint64_t rust_openssl_ssl_ctx_options_c_to_rust(long cval) {{").unwrap();
    writeln!(shim,"    uint64_t rustval=cval&COPY_MASK;").unwrap();
    for &(name,_) in options {
        writeln!(shim,"    if (cval&{0}) rustval|=RUST_{0};",name).unwrap();
    }
    writeln!(shim,"    return rustval;").unwrap();
    writeln!(shim,"}}").unwrap();

    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_file = PathBuf::from(&out_dir).join("ssl_ctx_options_shim.c");
    let mut f = File::create(&dest_file).unwrap();

    f.write_all(shim.as_bytes()).unwrap();

    dest_file
}

fn build_openssl_shim(include_paths: &[PathBuf]) {
    let options_shim_file = generate_options_shim();
    let mut config = gcc::Config::new();

    for path in include_paths {
@@ -73,6 +132,7 @@ fn build_openssl_shim(include_paths: &[PathBuf]) {
    }

    config.file("src/openssl_shim.c")
        .file(options_shim_file)
        .compile("libopenssl_shim.a");
}

+26 −6
Original line number Diff line number Diff line
@@ -155,6 +155,14 @@ pub const SSL_TLSEXT_ERR_ALERT_WARNING: c_int = 1;
pub const SSL_TLSEXT_ERR_ALERT_FATAL: c_int = 2;
pub const SSL_TLSEXT_ERR_NOACK: c_int = 3;

macro_rules! import_options {
    ( $( $name:ident $val:expr  )* ) => {
       $( pub const $name: u64 = $val; )*
    };
}

include!("ssl_options.rs");

#[cfg(feature = "npn")]
pub const OPENSSL_NPN_UNSUPPORTED: c_int = 0;
#[cfg(feature = "npn")]
@@ -262,8 +270,23 @@ pub fn init() {
    }
}

pub unsafe fn SSL_CTX_set_options(ssl: *mut SSL_CTX, op: u64) -> u64 {
    rust_openssl_ssl_ctx_options_c_to_rust(SSL_CTX_set_options_shim(ssl, rust_openssl_ssl_ctx_options_rust_to_c(op)))
}

pub unsafe fn SSL_CTX_get_options(ssl: *mut SSL_CTX) -> u64 {
    rust_openssl_ssl_ctx_options_c_to_rust(SSL_CTX_get_options_shim(ssl))
}

pub unsafe fn SSL_CTX_clear_options(ssl: *mut SSL_CTX, op: u64) -> u64 {
    rust_openssl_ssl_ctx_options_c_to_rust(SSL_CTX_clear_options_shim(ssl, rust_openssl_ssl_ctx_options_rust_to_c(op)))
}

// True functions
extern "C" {
    fn rust_openssl_ssl_ctx_options_rust_to_c(rustval: u64) -> c_long;
    fn rust_openssl_ssl_ctx_options_c_to_rust(cval: c_long) -> u64;

    pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int;
    pub fn ASN1_STRING_type_new(ty: c_int) -> *mut ASN1_STRING;
    pub fn ASN1_TIME_free(tm: *mut ASN1_TIME);
@@ -616,12 +639,9 @@ extern "C" {
    pub fn BIO_eof(b: *mut BIO) -> c_int;
    #[link_name = "BIO_set_mem_eof_return_shim"]
    pub fn BIO_set_mem_eof_return(b: *mut BIO, v: c_int);
    #[link_name = "SSL_CTX_set_options_shim"]
    pub fn SSL_CTX_set_options(ctx: *mut SSL_CTX, options: c_long) -> c_long;
    #[link_name = "SSL_CTX_get_options_shim"]
    pub fn SSL_CTX_get_options(ctx: *mut SSL_CTX) -> c_long;
    #[link_name = "SSL_CTX_clear_options_shim"]
    pub fn SSL_CTX_clear_options(ctx: *mut SSL_CTX, options: c_long) -> c_long;
    pub fn SSL_CTX_set_options_shim(ctx: *mut SSL_CTX, options: c_long) -> c_long;
    pub fn SSL_CTX_get_options_shim(ctx: *mut SSL_CTX) -> c_long;
    pub fn SSL_CTX_clear_options_shim(ctx: *mut SSL_CTX, options: c_long) -> c_long;
    #[link_name = "SSL_CTX_add_extra_chain_cert_shim"]
    pub fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) -> c_long;
    #[link_name = "SSL_CTX_set_read_ahead_shim"]
+46 −0
Original line number Diff line number Diff line
import_options!{
// The following values are directly from recent OpenSSL
SSL_OP_MICROSOFT_SESS_ID_BUG                   0x00000001
SSL_OP_NETSCAPE_CHALLENGE_BUG                  0x00000002
SSL_OP_LEGACY_SERVER_CONNECT                   0x00000004
SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG        0x00000008
SSL_OP_TLSEXT_PADDING                          0x00000010
SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER              0x00000020
SSL_OP_SAFARI_ECDHE_ECDSA_BUG                  0x00000040
SSL_OP_SSLEAY_080_CLIENT_DH_BUG                0x00000080
SSL_OP_TLS_D5_BUG                              0x00000100
SSL_OP_TLS_BLOCK_PADDING_BUG                   0x00000200
// unused:                                     0x00000400
SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS             0x00000800
SSL_OP_NO_QUERY_MTU                            0x00001000
SSL_OP_COOKIE_EXCHANGE                         0x00002000
SSL_OP_NO_TICKET                               0x00004000
SSL_OP_CISCO_ANYCONNECT                        0x00008000
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION  0x00010000
SSL_OP_NO_COMPRESSION                          0x00020000
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION       0x00040000
SSL_OP_SINGLE_ECDH_USE                         0x00080000
SSL_OP_SINGLE_DH_USE                           0x00100000
// unused:                                     0x00200000
SSL_OP_CIPHER_SERVER_PREFERENCE                0x00400000
SSL_OP_TLS_ROLLBACK_BUG                        0x00800000
SSL_OP_NO_SSLv2                                0x01000000
SSL_OP_NO_SSLv3                                0x02000000
SSL_OP_NO_DTLSv1                               0x04000000
SSL_OP_NO_TLSv1                                0x04000000
SSL_OP_NO_DTLSv1_2                             0x08000000
SSL_OP_NO_TLSv1_2                              0x08000000
SSL_OP_NO_TLSv1_1                              0x10000000
SSL_OP_NETSCAPE_CA_DN_BUG                      0x20000000
SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG         0x40000000
SSL_OP_CRYPTOPRO_TLSEXT_BUG                    0x80000000

// The following values were in 32-bit range in old OpenSSL
SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG             0x100000000
SSL_OP_MSIE_SSLV2_RSA_PADDING                  0x200000000
SSL_OP_PKCS1_CHECK_1                           0x400000000
SSL_OP_PKCS1_CHECK_2                           0x800000000

// The following values were redefined to 0 for security reasons
SSL_OP_EPHEMERAL_RSA                           0x0
}
+46 −29
Original line number Diff line number Diff line
@@ -46,35 +46,52 @@ fn init() {
}

bitflags! {
    flags SslContextOptions: c_long {
        const SSL_OP_LEGACY_SERVER_CONNECT = 0x00000004,
        const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 0x00000008,
        const SSL_OP_TLSEXT_PADDING = 0x00000010,
        const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 0x00000020,
        const SSL_OP_SAFARI_ECDHE_ECDSA_BUG = 0x00000040,
        const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 0x00000080,
        const SSL_OP_TLS_D5_BUG = 0x00000100,
        const SSL_OP_TLS_BLOCK_PADDING_BUG = 0x00000200,
        const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00000800,
        const SSL_OP_ALL = 0x80000BFF,
        const SSL_OP_NO_QUERY_MTU = 0x00001000,
        const SSL_OP_COOKIE_EXCHANGE = 0x00002000,
        const SSL_OP_NO_TICKET = 0x00004000,
        const SSL_OP_CISCO_ANYCONNECT = 0x00008000,
        const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00010000,
        const SSL_OP_NO_COMPRESSION = 0x00020000,
        const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = 0x00040000,
        const SSL_OP_SINGLE_ECDH_USE = 0x00080000,
        const SSL_OP_SINGLE_DH_USE = 0x00100000,
        const SSL_OP_CIPHER_SERVER_PREFERENCE = 0x00400000,
        const SSL_OP_TLS_ROLLBACK_BUG = 0x00800000,
        const SSL_OP_NO_SSLV2 = 0x00000000,
        const SSL_OP_NO_SSLV3 = 0x02000000,
        const SSL_OP_NO_TLSV1 = 0x04000000,
        const SSL_OP_NO_TLSV1_2 = 0x08000000,
        const SSL_OP_NO_TLSV1_1 = 0x10000000,
        const SSL_OP_NO_DTLSV1 = 0x04000000,
        const SSL_OP_NO_DTLSV1_2 = 0x08000000
    flags SslContextOptions: u64 {
        const SSL_OP_MICROSOFT_SESS_ID_BUG                    = ffi::SSL_OP_MICROSOFT_SESS_ID_BUG,
        const SSL_OP_NETSCAPE_CHALLENGE_BUG                   = ffi::SSL_OP_NETSCAPE_CHALLENGE_BUG,
        const SSL_OP_LEGACY_SERVER_CONNECT                    = ffi::SSL_OP_LEGACY_SERVER_CONNECT,
        const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG         = ffi::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG,
        const SSL_OP_TLSEXT_PADDING                           = ffi::SSL_OP_TLSEXT_PADDING,
        const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER               = ffi::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER,
        const SSL_OP_SAFARI_ECDHE_ECDSA_BUG                   = ffi::SSL_OP_SAFARI_ECDHE_ECDSA_BUG,
        const SSL_OP_SSLEAY_080_CLIENT_DH_BUG                 = ffi::SSL_OP_SSLEAY_080_CLIENT_DH_BUG,
        const SSL_OP_TLS_D5_BUG                               = ffi::SSL_OP_TLS_D5_BUG,
        const SSL_OP_TLS_BLOCK_PADDING_BUG                    = ffi::SSL_OP_TLS_BLOCK_PADDING_BUG,
        const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS,
        const SSL_OP_NO_QUERY_MTU                             = ffi::SSL_OP_NO_QUERY_MTU,
        const SSL_OP_COOKIE_EXCHANGE                          = ffi::SSL_OP_COOKIE_EXCHANGE,
        const SSL_OP_NO_TICKET                                = ffi::SSL_OP_NO_TICKET,
        const SSL_OP_CISCO_ANYCONNECT                         = ffi::SSL_OP_CISCO_ANYCONNECT,
        const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION   = ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION,
        const SSL_OP_NO_COMPRESSION                           = ffi::SSL_OP_NO_COMPRESSION,
        const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION        = ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION,
        const SSL_OP_SINGLE_ECDH_USE                          = ffi::SSL_OP_SINGLE_ECDH_USE,
        const SSL_OP_SINGLE_DH_USE                            = ffi::SSL_OP_SINGLE_DH_USE,
        const SSL_OP_CIPHER_SERVER_PREFERENCE                 = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE,
        const SSL_OP_TLS_ROLLBACK_BUG                         = ffi::SSL_OP_TLS_ROLLBACK_BUG,
        const SSL_OP_NO_SSLV2                                 = ffi::SSL_OP_NO_SSLv2,
        const SSL_OP_NO_SSLV3                                 = ffi::SSL_OP_NO_SSLv3,
        const SSL_OP_NO_DTLSV1                                = ffi::SSL_OP_NO_DTLSv1,
        const SSL_OP_NO_TLSV1                                 = ffi::SSL_OP_NO_TLSv1,
        const SSL_OP_NO_DTLSV1_2                              = ffi::SSL_OP_NO_DTLSv1_2,
        const SSL_OP_NO_TLSV1_2                               = ffi::SSL_OP_NO_TLSv1_2,
        const SSL_OP_NO_TLSV1_1                               = ffi::SSL_OP_NO_TLSv1_1,
        const SSL_OP_NETSCAPE_CA_DN_BUG                       = ffi::SSL_OP_NETSCAPE_CA_DN_BUG,
        const SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG          = ffi::SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG,
        const SSL_OP_CRYPTOPRO_TLSEXT_BUG                     = ffi::SSL_OP_CRYPTOPRO_TLSEXT_BUG,
        const SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG              = ffi::SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG,
        const SSL_OP_MSIE_SSLV2_RSA_PADDING                   = ffi::SSL_OP_MSIE_SSLV2_RSA_PADDING,
        const SSL_OP_PKCS1_CHECK_1                            = ffi::SSL_OP_PKCS1_CHECK_1,
        const SSL_OP_PKCS1_CHECK_2                            = ffi::SSL_OP_PKCS1_CHECK_2,
        const SSL_OP_EPHEMERAL_RSA                            = ffi::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
                                  |SSL_OP_SAFARI_ECDHE_ECDSA_BUG.bits|SSL_OP_SSLEAY_080_CLIENT_DH_BUG.bits
                                  |SSL_OP_TLS_D5_BUG.bits|SSL_OP_TLS_BLOCK_PADDING_BUG.bits
                                  |SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS.bits|SSL_OP_CRYPTOPRO_TLSEXT_BUG.bits,
        const SSL_OP_NO_SSL_MASK = SSL_OP_NO_SSLV2.bits|SSL_OP_NO_SSLV3.bits|SSL_OP_NO_TLSV1.bits
                                  |SSL_OP_NO_TLSV1_1.bits|SSL_OP_NO_TLSV1_2.bits,
    }
}