From c8118482a3a49ba1c517a4c9d6da615afa308df7 Mon Sep 17 00:00:00 2001 From: pNext <843609378@qq.com> Date: Sat, 10 Dec 2022 18:25:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96keylog.rs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rust/rust_project/src/vtls/keylog.rs | 350 ++++++++++++++++----------- 1 file changed, 202 insertions(+), 148 deletions(-) diff --git a/rust/rust_project/src/vtls/keylog.rs b/rust/rust_project/src/vtls/keylog.rs index f699039..54e699c 100644 --- a/rust/rust_project/src/vtls/keylog.rs +++ b/rust/rust_project/src/vtls/keylog.rs @@ -17,183 +17,237 @@ use rust_ffi::src::ffi_alias::type_alias::*; use rust_ffi::src::ffi_fun::fun_call::*; use rust_ffi::src::ffi_struct::struct_define::*; +const FOPEN_APPENDTEXT: *const libc::c_char = b"a\0" as *const u8 as *const libc::c_char; +const _IOLBF: i32 = 1; +const _IONBF: i32 = 2; + +const KEYLOG_LABEL_MAXLEN: u64 = + (::std::mem::size_of::<[libc::c_char; 32]>() as u64).wrapping_sub(1 as u64); + +const CLIENT_RANDOM_SIZE: u64 = 32; + +/* + * The master secret in TLS 1.2 and before is always 48 bytes. In TLS 1.3, the + * secret size depends on the cipher suite's hash function which is 32 bytes + * for SHA-256 and 48 bytes for SHA-384. + */ +const SECRET_MAXLEN: u64 = 48; + +/* The fp for the open SSLKEYLOGFILE, or NULL if not open */ static mut keylog_file_fp: *mut FILE = 0 as *const FILE as *mut FILE; + #[no_mangle] -pub unsafe extern "C" fn Curl_tls_keylog_open() { - let mut keylog_file_name: *mut libc::c_char = 0 as *mut libc::c_char; - if keylog_file_fp.is_null() { - keylog_file_name = curl_getenv(b"SSLKEYLOGFILE\0" as *const u8 as *const libc::c_char); - if !keylog_file_name.is_null() { - match () { - #[cfg(not(CURLDEBUG))] - _ => { - keylog_file_fp = - fopen(keylog_file_name, b"a\0" as *const u8 as *const libc::c_char); - } - #[cfg(CURLDEBUG)] - _ => { - keylog_file_fp = curl_dbg_fopen( - keylog_file_name, - b"a\0" as *const u8 as *const libc::c_char, - 53 as libc::c_int, - b"vtls/keylog.c\0" as *const u8 as *const libc::c_char, - ); - } - } - if !keylog_file_fp.is_null() { - #[cfg(WIN32)] - let flag: bool = setvbuf( - keylog_file_fp, - 0 as *mut libc::c_char, - 1 as libc::c_int, - 0 as libc::c_int as size_t, - ) != 0; - #[cfg(not(WIN32))] - let flag: bool = setvbuf( - keylog_file_fp, - 0 as *mut libc::c_char, - 1 as libc::c_int, - 4096 as libc::c_int as size_t, - ) != 0; - if flag { +pub extern "C" fn Curl_tls_keylog_open() { + unsafe { + let mut keylog_file_name: *mut libc::c_char = 0 as *mut libc::c_char; + + if keylog_file_fp.is_null() { + keylog_file_name = curl_getenv(b"SSLKEYLOGFILE\0" as *const u8 as *const libc::c_char); + if !keylog_file_name.is_null() { + match () { #[cfg(not(CURLDEBUG))] - fclose(keylog_file_fp); + _ => { + keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT); + } #[cfg(CURLDEBUG)] - curl_dbg_fclose( + _ => { + keylog_file_fp = curl_dbg_fopen( + keylog_file_name, + b"a\0" as *const u8 as *const libc::c_char, + 53 as i32, + b"vtls/keylog.c\0" as *const u8 as *const libc::c_char, + ); + } + } + if !keylog_file_fp.is_null() { + #[cfg(WIN32)] + let flag: bool = setvbuf( + keylog_file_fp, + 0 as *mut libc::c_char, + _IONBF, + 0 as size_t, + ) != 0; + #[cfg(not(WIN32))] + let flag: bool = setvbuf( keylog_file_fp, - 61 as libc::c_int, - b"vtls/keylog.c\0" as *const u8 as *const libc::c_char, - ); - keylog_file_fp = 0 as *mut FILE; + 0 as *mut libc::c_char, + _IOLBF, + 4096 as size_t, + ) != 0; + if flag { + #[cfg(not(CURLDEBUG))] + fclose(keylog_file_fp); + #[cfg(CURLDEBUG)] + curl_dbg_fclose( + keylog_file_fp, + 61, + b"vtls/keylog.c\0" as *const u8 as *const libc::c_char, + ); + keylog_file_fp = 0 as *mut FILE; + } } + #[cfg(not(CURLDEBUG))] + Curl_cfree.expect("non-null function pointer")( + keylog_file_name as *mut libc::c_void, + ); + #[cfg(CURLDEBUG)] + curl_dbg_free( + keylog_file_name as *mut libc::c_void, + 65, + b"vtls/keylog.c\0" as *const u8 as *const libc::c_char, + ); + keylog_file_name = 0 as *mut libc::c_char; } + } + } +} + +#[no_mangle] +pub extern "C" fn Curl_tls_keylog_close() { + unsafe { + if !keylog_file_fp.is_null() { + #[cfg(not(CURLDEBUG))] + fclose(keylog_file_fp); + #[cfg(CURLDEBUG)] + curl_dbg_fclose( + keylog_file_fp, + 74, + b"vtls/keylog.c\0" as *const u8 as *const libc::c_char, + ); + keylog_file_fp = 0 as *mut FILE; + } + if !keylog_file_fp.is_null() { #[cfg(not(CURLDEBUG))] - Curl_cfree.expect("non-null function pointer")(keylog_file_name as *mut libc::c_void); + fclose(keylog_file_fp); #[cfg(CURLDEBUG)] - curl_dbg_free( - keylog_file_name as *mut libc::c_void, - 65 as libc::c_int, + curl_dbg_fclose( + keylog_file_fp, + 74, b"vtls/keylog.c\0" as *const u8 as *const libc::c_char, ); - keylog_file_name = 0 as *mut libc::c_char; + keylog_file_fp = 0 as *mut FILE; } } } + #[no_mangle] -pub unsafe extern "C" fn Curl_tls_keylog_close() { - if !keylog_file_fp.is_null() { - #[cfg(not(CURLDEBUG))] - fclose(keylog_file_fp); - #[cfg(CURLDEBUG)] - curl_dbg_fclose( - keylog_file_fp, - 74 as libc::c_int, - b"vtls/keylog.c\0" as *const u8 as *const libc::c_char, - ); - keylog_file_fp = 0 as *mut FILE; +pub extern "C" fn Curl_tls_keylog_enabled() -> bool { + unsafe { + return !keylog_file_fp.is_null(); } } + #[no_mangle] -pub unsafe extern "C" fn Curl_tls_keylog_enabled() -> bool { - return !keylog_file_fp.is_null(); -} -#[no_mangle] -pub unsafe extern "C" fn Curl_tls_keylog_write_line(mut line: *const libc::c_char) -> bool { - let mut linelen: size_t = 0; - let mut buf: [libc::c_char; 256] = [0; 256]; - if keylog_file_fp.is_null() || line.is_null() { - return 0 as libc::c_int != 0; - } - linelen = strlen(line); - if linelen == 0 as libc::c_int as libc::c_ulong - || linelen - > (::std::mem::size_of::<[libc::c_char; 256]>() as libc::c_ulong) - .wrapping_sub(2 as libc::c_int as libc::c_ulong) - { - return 0 as libc::c_int != 0; - } - memcpy( - buf.as_mut_ptr() as *mut libc::c_void, - line as *const libc::c_void, - linelen, - ); - if *line.offset(linelen.wrapping_sub(1 as libc::c_int as libc::c_ulong) as isize) as libc::c_int - != '\n' as i32 - { - let fresh0 = linelen; - linelen = linelen.wrapping_add(1); - buf[fresh0 as usize] = '\n' as i32 as libc::c_char; +pub extern "C" fn Curl_tls_keylog_write_line(mut line: *const libc::c_char) -> bool { + unsafe { + /* The current maximum valid keylog line length LF and NUL is 195. */ + let mut linelen: size_t = 0; + let mut buf: [libc::c_char; 256] = [0; 256]; + + if keylog_file_fp.is_null() || line.is_null() { + return false; + } + + linelen = strlen(line); + if linelen == 0 + || linelen + > (::std::mem::size_of::<[libc::c_char; 256]>() as u64) + .wrapping_sub(2) + { + /* Empty line or too big to fit in a LF and NUL. */ + return false; + } + + memcpy( + buf.as_mut_ptr() as *mut libc::c_void, + line as *const libc::c_void, + linelen, + ); + if *line.offset(linelen.wrapping_sub(1) as isize) as i32 != '\n' as i32 { + buf[linelen as usize] = '\n' as i32 as libc::c_char; + linelen = linelen.wrapping_add(1); + } + buf[linelen as usize] = '\0' as i32 as libc::c_char; + + /* Using fputs here instead of fprintf since libcurl's fprintf replacement + may not be thread-safe. */ + fputs(buf.as_mut_ptr(), keylog_file_fp); + return true; } - buf[linelen as usize] = '\0' as i32 as libc::c_char; - fputs(buf.as_mut_ptr(), keylog_file_fp); - return 1 as libc::c_int != 0; } + #[no_mangle] -pub unsafe extern "C" fn Curl_tls_keylog_write( +pub extern "C" fn Curl_tls_keylog_write( mut label: *const libc::c_char, - mut client_random: *const libc::c_uchar, - mut secret: *const libc::c_uchar, + mut client_random: *const u8, + mut secret: *const u8, mut secretlen: size_t, ) -> bool { - let mut hex: *const libc::c_char = b"0123456789ABCDEF\0" as *const u8 as *const libc::c_char; - let mut pos: size_t = 0; - let mut i: size_t = 0; - let mut line: [libc::c_char; 195] = [0; 195]; - if keylog_file_fp.is_null() { - return 0 as libc::c_int != 0; - } - pos = strlen(label); - if pos - > (::std::mem::size_of::<[libc::c_char; 32]>() as libc::c_ulong) - .wrapping_sub(1 as libc::c_int as libc::c_ulong) - || secretlen == 0 - || secretlen > 48 as libc::c_int as libc::c_ulong - { - return 0 as libc::c_int != 0; - } - memcpy( - line.as_mut_ptr() as *mut libc::c_void, - label as *const libc::c_void, - pos, - ); - let fresh1 = pos; - pos = pos.wrapping_add(1); - line[fresh1 as usize] = ' ' as i32 as libc::c_char; - i = 0 as libc::c_int as size_t; - while i < 32 as libc::c_int as libc::c_ulong { - let fresh2 = pos; - pos = pos.wrapping_add(1); - line[fresh2 as usize] = *hex.offset( - (*client_random.offset(i as isize) as libc::c_int >> 4 as libc::c_int) as isize, + unsafe { + let mut hex: *const libc::c_char = + b"0123456789ABCDEF\0" as *const u8 as *const libc::c_char; + let mut pos: size_t = 0; + let mut i: size_t = 0; + let mut line: [libc::c_char; + (KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 + 2 * SECRET_MAXLEN + 1 + 1) + as usize] = + [0; (KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 + 2 * SECRET_MAXLEN + 1 + 1) + as usize]; + + if keylog_file_fp.is_null() { + return false; + } + + pos = strlen(label); + if pos > KEYLOG_LABEL_MAXLEN || secretlen == 0 || secretlen > 48 { + /* Should never happen - sanity check anyway. */ + return false; + } + + memcpy( + line.as_mut_ptr() as *mut libc::c_void, + label as *const libc::c_void, + pos, ); - let fresh3 = pos; + line[pos as usize] = ' ' as i32 as libc::c_char; pos = pos.wrapping_add(1); - line[fresh3 as usize] = *hex.offset( - (*client_random.offset(i as isize) as libc::c_int & 0xf as libc::c_int) as isize, - ); - i = i.wrapping_add(1); - } - let fresh4 = pos; - pos = pos.wrapping_add(1); - line[fresh4 as usize] = ' ' as i32 as libc::c_char; - i = 0 as libc::c_int as size_t; - while i < secretlen { - let fresh5 = pos; + + /* Client Random */ + i = 0 as size_t; + while i < CLIENT_RANDOM_SIZE { + line[pos as usize] = + *hex.offset((*client_random.offset(i as isize) >> 4) as isize); + pos = pos.wrapping_add(1); + + line[pos as usize] = + *hex.offset((*client_random.offset(i as isize) as i32 & 0xf as i32) as isize); + pos = pos.wrapping_add(1); + + i = i.wrapping_add(1); + } + line[pos as usize] = ' ' as i32 as libc::c_char; pos = pos.wrapping_add(1); - line[fresh5 as usize] = - *hex.offset((*secret.offset(i as isize) as libc::c_int >> 4 as libc::c_int) as isize); - let fresh6 = pos; + + /* Secret */ + i = 0 as size_t; + while i < secretlen { + line[pos as usize] = + *hex.offset((*secret.offset(i as isize) as i32 >> 4 as i32) as isize); + pos = pos.wrapping_add(1); + line[pos as usize] = + *hex.offset((*secret.offset(i as isize) as i32 & 0xf as i32) as isize); + pos = pos.wrapping_add(1); + i = i.wrapping_add(1); + } + line[pos as usize] = '\n' as i32 as libc::c_char; pos = pos.wrapping_add(1); - line[fresh6 as usize] = - *hex.offset((*secret.offset(i as isize) as libc::c_int & 0xf as libc::c_int) as isize); - i = i.wrapping_add(1); + line[pos as usize] = '\0' as i32 as libc::c_char; + + /* Using fputs here instead of fprintf since libcurl's fprintf replacement + may not be thread-safe. */ + fputs(line.as_mut_ptr(), keylog_file_fp); + return true; } - let fresh7 = pos; - pos = pos.wrapping_add(1); - line[fresh7 as usize] = '\n' as i32 as libc::c_char; - line[pos as usize] = '\0' as i32 as libc::c_char; - fputs(line.as_mut_ptr(), keylog_file_fp); - return 1 as libc::c_int != 0; } #[cfg(test)] -- Gitee