Skip to content

Added function rustls_connection_last_error_msg #556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 98 additions & 13 deletions librustls/src/connection.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::cmp::min;
use std::io::{ErrorKind, Read, Write};
use std::{ffi::c_void, ptr::null};
use std::{ptr::null_mut, slice};
Expand Down Expand Up @@ -27,6 +28,7 @@ pub(crate) struct Connection {
conn: rustls::Connection,
userdata: *mut c_void,
log_callback: rustls_log_callback,
last_error_msg: Option<String>,
}

impl Connection {
Expand All @@ -35,6 +37,7 @@ impl Connection {
conn: conn.into(),
userdata: null_mut(),
log_callback: None,
last_error_msg: None,
}
}

Expand All @@ -43,6 +46,7 @@ impl Connection {
conn: conn.into(),
userdata: null_mut(),
log_callback: None,
last_error_msg: None,
}
}

Expand Down Expand Up @@ -142,14 +146,18 @@ impl rustls_connection {
ffi_panic_boundary! {
let conn = try_mut_from_ptr!(conn);
if out_n.is_null() {
conn.last_error_msg = Some("EINVAL".to_owned());
return rustls_io_result(EINVAL);
}
let callback = try_callback!(callback);

let mut reader = CallbackReader { callback, userdata };
let n_read = match conn.read_tls(&mut reader) {
Ok(n) => n,
Err(e) => return rustls_io_result(e.raw_os_error().unwrap_or(EIO)),
Err(e) => {
conn.last_error_msg = Some(format!("{}", e));
return rustls_io_result(e.raw_os_error().unwrap_or(EIO));
}
};
unsafe {
*out_n = n_read;
Expand Down Expand Up @@ -179,14 +187,18 @@ impl rustls_connection {
ffi_panic_boundary! {
let conn = try_mut_from_ptr!(conn);
if out_n.is_null() {
conn.last_error_msg = Some("EINVAL".to_owned());
return rustls_io_result(EINVAL);
}
let callback = try_callback!(callback);

let mut writer = CallbackWriter { callback, userdata };
let n_written = match conn.write_tls(&mut writer) {
Ok(n) => n,
Err(e) => return rustls_io_result(e.raw_os_error().unwrap_or(EIO)),
Err(e) => {
conn.last_error_msg = Some(format!("{}", e));
return rustls_io_result(e.raw_os_error().unwrap_or(EIO));
}
};
unsafe {
*out_n = n_written;
Expand Down Expand Up @@ -216,14 +228,18 @@ impl rustls_connection {
ffi_panic_boundary! {
let conn = try_mut_from_ptr!(conn);
if out_n.is_null() {
conn.last_error_msg = Some("EINVAL".to_owned());
return rustls_io_result(EINVAL);
}
let callback = try_callback!(callback);

let mut writer = VectoredCallbackWriter { callback, userdata };
let n_written = match conn.write_tls(&mut writer) {
Ok(n) => n,
Err(e) => return rustls_io_result(e.raw_os_error().unwrap_or(EIO)),
Err(e) => {
conn.last_error_msg = Some(format!("{}", e));
return rustls_io_result(e.raw_os_error().unwrap_or(EIO));
}
};
unsafe {
*out_n = n_written;
Expand All @@ -245,15 +261,24 @@ impl rustls_connection {
let conn = try_mut_from_ptr!(conn);
let guard = match userdata_push(conn.userdata, conn.log_callback) {
Ok(g) => g,
Err(_) => return rustls_result::Panic,
Err(e) => {
conn.last_error_msg = Some(format!("{:?}", e));
return rustls_result::Panic;
}
};
let result = match conn.process_new_packets() {
Ok(_) => rustls_result::Ok,
Err(e) => map_error(e),
Err(e) => {
conn.last_error_msg = Some(format!("{}", e));
map_error(e)
}
};
match guard.try_drop() {
Ok(()) => result,
Err(_) => rustls_result::Panic,
Err(e) => {
conn.last_error_msg = Some(format!("{:?}", e));
rustls_result::Panic
}
}
}
}
Expand Down Expand Up @@ -337,7 +362,11 @@ impl rustls_connection {
ffi_panic_boundary! {
match try_mut_from_ptr!(conn).refresh_traffic_keys() {
Ok(_) => rustls_result::Ok,
Err(e) => map_error(e),
Err(e) => {
let conn = try_mut_from_ptr!(conn);
conn.last_error_msg = Some(format!("{}", e));
map_error(e)
}
}
}
}
Expand Down Expand Up @@ -508,11 +537,16 @@ impl rustls_connection {
let conn = try_mut_from_ptr!(conn);
let write_buf = try_slice!(buf, count);
if out_n.is_null() {
return rustls_result::NullParameter;
let res = rustls_result::NullParameter;
conn.last_error_msg = Some(format!("{:?}", res));
return res;
}
let n_written = match conn.writer().write(write_buf) {
Ok(n) => n,
Err(_) => return rustls_result::Io,
Err(e) => {
conn.last_error_msg = Some(format!("{}", e));
return rustls_result::Io;
}
};
unsafe {
*out_n = n_written;
Expand Down Expand Up @@ -543,9 +577,13 @@ impl rustls_connection {
ffi_panic_boundary! {
let conn = try_mut_from_ptr!(conn);
if buf.is_null() {
return rustls_result::NullParameter;
let res = rustls_result::NullParameter;
conn.last_error_msg = Some(format!("{:?}", res));
return res;
}
if out_n.is_null() {
let res = rustls_result::NullParameter;
conn.last_error_msg = Some(format!("{:?}", res));
return rustls_result::NullParameter;
}

Expand All @@ -556,12 +594,17 @@ impl rustls_connection {
let n_read = match conn.reader().read(read_buf) {
Ok(n) => n,
Err(e) if e.kind() == ErrorKind::UnexpectedEof => {
conn.last_error_msg = Some(format!("{}", e));
return rustls_result::UnexpectedEof;
}
Err(e) if e.kind() == ErrorKind::WouldBlock => {
conn.last_error_msg = Some(format!("{}", e));
return rustls_result::PlaintextEmpty;
}
Err(_) => return rustls_result::Io,
Err(e) => {
conn.last_error_msg = Some(format!("{}", e));
return rustls_result::Io;
}
};
unsafe {
*out_n = n_read;
Expand Down Expand Up @@ -594,19 +637,26 @@ impl rustls_connection {
ffi_panic_boundary! {
let conn = try_mut_from_ptr!(conn);
if buf.is_null() || out_n.is_null() {
return rustls_result::NullParameter;
let res = rustls_result::NullParameter;
conn.last_error_msg = Some(format!("{:?}", res));
return res;
}
let mut read_buf: std::io::BorrowedBuf<'_> = try_slice_mut!(buf, count).into();

let n_read = match conn.reader().read_buf(read_buf.unfilled()) {
Ok(()) => read_buf.filled().len(),
Err(e) if e.kind() == ErrorKind::UnexpectedEof => {
conn.last_error_msg = Some(format!("{}", e));
return rustls_result::UnexpectedEof;
}
Err(e) if e.kind() == ErrorKind::WouldBlock => {
conn.last_error_msg = Some(format!("{}", e));
return rustls_result::PlaintextEmpty;
}
Err(_) => return rustls_result::Io,
Err(e) => {
conn.last_error_msg = Some(format!("{}", e));
return rustls_result::Io;
}
};
unsafe {
*out_n = n_read;
Expand All @@ -632,6 +682,41 @@ impl rustls_connection {
}
}

/// Read up to `count` bytes of the last error message into `buf`.
/// If there is any error message, store the number of bytes in *out_n and
/// returns `true`. If there is no last error message, stores 0 in *out_n
/// and returns `false`.
#[no_mangle]
pub extern "C" fn rustls_connection_last_error_msg(
conn: &mut rustls_connection,
buf: *mut u8,
count: size_t,
out_n: *mut size_t,
) -> bool {
ffi_panic_boundary! {
let conn = try_ref_from_ptr!(conn);
match &conn.last_error_msg {
Some(msg) => {
let n = min(msg.len(), count);
if n > 0 {
let buf = try_slice_mut!(buf, n);
buf.copy_from_slice(msg.as_bytes());
}
unsafe {
*out_n = n;
}
true
}
None => {
unsafe {
*out_n = 0;
}
false
}
}
}
}

/// Free a rustls_connection. Calling with NULL is fine.
/// Must not be called twice with the same value.
#[no_mangle]
Expand Down
11 changes: 11 additions & 0 deletions librustls/src/rustls.h
Original file line number Diff line number Diff line change
Expand Up @@ -1868,6 +1868,17 @@ rustls_result rustls_connection_read_2(struct rustls_connection *conn,
*/
bool rustls_connection_fips(const struct rustls_connection *conn);

/**
* Read up to `count` bytes of the last error message into `buf`.
* If there is any error message, store the number of bytes in *out_n and
* returns `true`. If there is no last error message, stores 0 in *out_n
* and returns `false`.
*/
bool rustls_connection_last_error_msg(struct rustls_connection *conn,
uint8_t *buf,
size_t count,
size_t *out_n);

/**
* Free a rustls_connection. Calling with NULL is fine.
* Must not be called twice with the same value.
Expand Down
Loading