aboutsummaryrefslogtreecommitdiff
path: root/src/ssl/error.rs
blob: 56105253d2fbb51c5f2c80c338336a311b71f3b5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use libc::c_ulong;
use std::io::IoError;
use std::c_str::CString;

use ffi;

/// An SSL error
#[deriving(Show, Clone, PartialEq, Eq)]
pub enum SslError {
    /// The underlying stream has reported an error
    StreamError(IoError),
    /// The SSL session has been closed by the other end
    SslSessionClosed,
    /// An error in the OpenSSL library
    OpenSslErrors(Vec<OpensslError>)
}

/// An error from the OpenSSL library
#[deriving(Show, Clone, PartialEq, Eq)]
pub enum OpensslError {
    /// An unknown error
    UnknownError {
        /// The library reporting the error
        library: String,
        /// The function reporting the error
        function: String,
        /// The reason for the error
        reason: String
    }
}

fn get_lib(err: c_ulong) -> String {
    unsafe { CString::new(ffi::ERR_lib_error_string(err), false) }.to_string()
}

fn get_func(err: c_ulong) -> String {
    unsafe { CString::new(ffi::ERR_func_error_string(err), false).to_string() }
}

fn get_reason(err: c_ulong) -> String {
    unsafe { CString::new(ffi::ERR_reason_error_string(err), false).to_string() }
}

#[test]
#[ignore] // FIXME #65
fn test_uknown_error_should_have_correct_messages() {
    let err = 336032784;
    let library = get_lib(err);
    let function = get_func(err);
    let reason = get_reason(err);

    assert_eq!(library.as_slice(),"SSL routines");
    assert_eq!(function.as_slice(), "SSL23_GET_SERVER_HELLO");
    assert_eq!(reason.as_slice(), "sslv3 alert handshake failure");
}

impl SslError {
    /// Creates a new `OpenSslErrors` with the current contents of the error
    /// stack.
    pub fn get() -> SslError {
        let mut errs = vec!();
        loop {
            match unsafe { ffi::ERR_get_error() } {
                0 => break,
                err => errs.push(UnknownError {
                    library: get_lib(err),
                    function: get_func(err),
                    reason: get_reason(err)
                })
            }
        }
        OpenSslErrors(errs)
    }
}