Commit 3ba768bc authored by Valerii Hiora's avatar Valerii Hiora
Browse files

Fixed incorrect EOF handling in MemBio, added error description

Actually, EOF wasn't handled at all and it caused `mem_bio.read_to_end()` to fail. Which in turn failed all `write_pem` implementations.
parent e4b8b5e6
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
use libc::{c_void, c_int};
use std::io::{IoResult, IoError, OtherIoError};
use std::io::{EndOfFile, IoResult, IoError, OtherIoError};
use std::io::{Reader, Writer};
use std::ptr;

@@ -62,9 +62,22 @@ impl Reader for MemBio {
                          buf.len() as c_int)
        };

        if ret < 0 {
            // FIXME: provide details from OpenSSL
            Err(IoError{kind: OtherIoError, desc: "mem bio read error", detail: None})
        if ret <= 0 {
            let is_eof = unsafe { ffi::BIO_eof(self.bio) };
            let err = if is_eof {
                IoError {
                    kind: EndOfFile,
                    desc: "MemBio EOF",
                    detail: None
                }
            } else {
                IoError {
                    kind: OtherIoError,
                    desc: "MemBio read error",
                    detail: Some(format!("{}", SslError::get()))
                }
            };
            Err(err)
        } else {
            Ok(ret as uint)
        }
@@ -78,8 +91,11 @@ impl Writer for MemBio {
                           buf.len() as c_int)
        };
        if buf.len() != ret as uint {
            // FIXME: provide details from OpenSSL
            Err(IoError{kind: OtherIoError, desc: "mem bio write error", detail: None})
            Err(IoError {
                kind: OtherIoError,
                desc: "MemBio write error",
                detail: Some(format!("{}", SslError::get()))
            })
        } else {
            Ok(())
        }

src/ffi.rs

100644 → 100755
+11 −1
Original line number Diff line number Diff line
#![allow(non_camel_case_types, non_uppercase_statics, non_snake_case)]
#![allow(dead_code)]
use libc::{c_void, c_int, c_char, c_ulong, c_long, c_uint, c_uchar, size_t};
use std::ptr;

pub type ASN1_INTEGER = c_void;
pub type ASN1_STRING = c_void;
@@ -84,6 +85,8 @@ pub type PrivateKeyWriteCallback = extern "C" fn(buf: *mut c_char, size: c_int,
                                                 rwflag: c_int, user_data: *mut c_void)
                                                 -> c_int;

pub static BIO_CTRL_EOF: c_int = 2;

pub static CRYPTO_LOCK: c_int = 1;

pub static MBSTRING_ASC:  c_int = MBSTRING_FLAG | 1;
@@ -195,12 +198,19 @@ extern "C" {
    pub fn bn_is_zero(a: *mut BIGNUM) -> c_int;
}

// Functions converted from macros
pub unsafe fn BIO_eof(b: *mut BIO) -> bool {
    BIO_ctrl(b, BIO_CTRL_EOF, 0, ptr::null_mut()) == 1
}

// True functions
extern "C" {
    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);

    pub fn BIO_free_all(a: *mut BIO);
    pub fn BIO_ctrl(b: *mut BIO, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long;
    pub fn BIO_free_all(b: *mut BIO);
    pub fn BIO_new(type_: *const BIO_METHOD) -> *mut BIO;
    pub fn BIO_read(b: *mut BIO, buf: *mut c_void, len: c_int) -> c_int;
    pub fn BIO_write(b: *mut BIO, buf: *const c_void, len: c_int) -> c_int;
+17 −1
Original line number Diff line number Diff line
use std::io::Writer;
use std::io::{File, Open, Write, Writer};
use std::io::net::tcp::TcpStream;
use std::num::FromStrRadix;
use std::str;
@@ -218,6 +218,22 @@ fn test_cert_gen() {

    let res = gen.generate();
    assert!(res.is_ok());

    let (cert, pkey) = res.unwrap();

    #[cfg(unix)]
    static NULL_PATH: &'static str = "/dev/null";
    #[cfg(windows)]
    static NULL_PATH: &'static str = "nul";

    let cert_path = Path::new(NULL_PATH);
    let mut file = File::open_mode(&cert_path, Open, Write).unwrap();
    assert!(cert.write_pem(&mut file).is_ok());

    let key_path = Path::new(NULL_PATH);
    let mut file = File::open_mode(&key_path, Open, Write).unwrap();
    assert!(pkey.write_pem(&mut file).is_ok());

    // FIXME: check data in result to be correct, needs implementation
    // of X509 getters
}