diff --git a/src/internal.rs b/src/internal.rs index ea65c5b..dcd3800 100644 --- a/src/internal.rs +++ b/src/internal.rs @@ -30,17 +30,14 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// TODO(tarcieri): investigate and remove dead code -#![allow(non_upper_case_globals, dead_code)] -#![allow(clippy::missing_safety_doc)] - use crate::consts::*; use des::{ block_cipher_trait::{generic_array::GenericArray, BlockCipher}, TdesEde3, }; -use libc::{c_char, c_int, fclose, feof, fgets, fopen, getenv, sscanf, strcasecmp, strcmp}; -use std::ffi::{CStr, CString}; +use std::env; +use std::fs::File; +use std::io::{BufRead, BufReader}; use zeroize::Zeroize; /// 3DES keys. The three subkeys are concatenated. @@ -50,10 +47,6 @@ impl DesKey { pub fn from_bytes(bytes: [u8; DES_LEN_3DES]) -> Self { DesKey(bytes) } - - pub fn write(&self, out: &mut [u8]) { - out.copy_from_slice(&self.0); - } } impl AsRef<[u8; 24]> for DesKey { @@ -98,7 +91,7 @@ pub fn yk_des_is_weak_key(key: &[u8; DES_LEN_3DES]) -> bool { /// %T Security for Computer Networks /// %I John Wiley & Sons /// %D 1984 - const weak_keys: [[u8; DES_LEN_DES]; 16] = [ + const WEAK_KEYS: [[u8; DES_LEN_DES]; 16] = [ // weak keys [0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01], [0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], @@ -135,7 +128,7 @@ pub fn yk_des_is_weak_key(key: &[u8; DES_LEN_3DES]) -> bool { // check odd parity key against table by DES key block let mut rv = false; - for weak_key in weak_keys.iter() { + for weak_key in WEAK_KEYS.iter() { if weak_key == &tmp[0..DES_LEN_DES] || weak_key == &tmp[DES_LEN_DES..2 * DES_LEN_DES] || weak_key == &tmp[2 * DES_LEN_DES..3 * DES_LEN_DES] @@ -149,23 +142,6 @@ pub fn yk_des_is_weak_key(key: &[u8; DES_LEN_3DES]) -> bool { rv } -/// PKCS#5 error types -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[repr(i32)] -pub enum Pkcs5ErrorKind { - /// OK - Ok = 0, - - /// General error - GeneralError = -1, -} - -/// Strip whitespace -// TODO(tarcieri): implement this -pub unsafe fn _strip_ws(sz: *mut c_char) -> *mut c_char { - sz -} - /// Source of how a setting was configured #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum SettingSource { @@ -190,105 +166,65 @@ pub struct SettingBool { } /// Get a boolean config value -pub unsafe fn _get_bool_config(sz_setting: *const c_char) -> SettingBool { +pub fn _get_bool_config(key: &str) -> SettingBool { let mut setting: SettingBool = SettingBool { value: false, source: SettingSource::Default, }; - let mut sz_line = [0u8; 256]; - let mut psz_name: *mut c_char; - let mut psz_value: *mut c_char; - let mut sz_name = [0u8; 256]; - let mut sz_value = [0u8; 256]; - let pf = fopen( - b"/etc/yubico/yubikeypiv.conf\0".as_ptr() as *const c_char, - b"r\0".as_ptr() as *const c_char, - ); + if let Ok(f) = File::open("/etc/yubico/yubikeypiv.conf") { + for line in BufReader::new(f).lines() { + let line = match line { + Ok(line) => line, + _ => continue, + }; - if pf.is_null() { - return setting; + if line.starts_with('#') || line.starts_with('\r') || line.starts_with('\n') { + continue; + } + + let (name, value) = { + let mut parts = line.splitn(1, '='); + let name = parts.next(); + let value = parts.next(); + match (name, value, parts.next()) { + (Some(name), Some(value), None) => (name.trim(), value.trim()), + _ => continue, + } + }; + + if name == key { + setting.source = SettingSource::Admin; + setting.value = value == "1" || value == "true"; + break; + } + } } - while feof(pf) == 0 { - if fgets( - sz_line.as_mut_ptr() as *mut c_char, - sz_line.len() as c_int, - pf, - ) - .is_null() - { - continue; - } - - if sz_line[0] == b'#' { - continue; - } - - if sz_line[0] == b'\r' { - continue; - } - - if sz_line[0] == b'\n' { - continue; - } - - if sscanf( - sz_line.as_ptr() as *const c_char, - b"%255[^=]=%255s\0".as_ptr() as *const c_char, - sz_name.as_mut_ptr(), - sz_value.as_mut_ptr(), - ) != 2 - { - continue; - } - - psz_name = _strip_ws(sz_name.as_mut_ptr() as *mut c_char); - - if strcasecmp(psz_name, sz_setting) != 0 { - continue; - } - - psz_value = _strip_ws(sz_value.as_mut_ptr() as *mut c_char); - setting.source = SettingSource::Admin; - setting.value = strcmp(psz_value, b"1\0".as_ptr() as *const c_char) == 0 - || strcasecmp(psz_value, b"true\0".as_ptr() as *const c_char) == 0; - } - - fclose(pf); setting } /// Get a setting boolean from an environment variable -pub unsafe fn _get_bool_env(sz_setting: *const c_char) -> SettingBool { +pub fn _get_bool_env(key: &str) -> SettingBool { let mut setting: SettingBool = SettingBool { value: false, source: SettingSource::Default, }; - let sz_name = CString::new(format!( - "YUBIKEY_PIV_{}", - CStr::from_ptr(sz_setting).to_string_lossy() - )) - .unwrap(); - - let psz_value = getenv(sz_name.as_ptr()); - - if !psz_value.is_null() { + if let Ok(value) = env::var(format!("YUBIKEY_PIV_{}", key)) { setting.source = SettingSource::User; - setting.value = strcmp(psz_value, b"1\0".as_ptr() as *const c_char) == 0 - || strcasecmp(psz_value, b"true\0".as_ptr() as *const c_char) == 0; + setting.value = value == "1" || value == "true"; } setting } /// Get a setting boolean -pub unsafe fn setting_get_bool(sz_setting: *const c_char, def: bool) -> SettingBool { - let mut setting = _get_bool_config(sz_setting); +pub fn setting_get_bool(key: &str, def: bool) -> SettingBool { + let mut setting = _get_bool_config(key); if setting.source == SettingSource::Default { - setting = _get_bool_env(sz_setting); + setting = _get_bool_env(key); } if setting.source == SettingSource::Default { diff --git a/src/util.rs b/src/util.rs index 2d45ec7..18d4b0d 100644 --- a/src/util.rs +++ b/src/util.rs @@ -41,7 +41,7 @@ use log::{error, warn}; use pbkdf2::pbkdf2; use sha1::Sha1; use std::ops::DerefMut; -use std::{ffi::CString, mem, os::raw::c_void, ptr}; +use std::{mem, os::raw::c_void, ptr}; use zeroize::{Zeroize, Zeroizing}; /// Cardholder Unique Identifier (CHUID) Template @@ -1002,8 +1002,7 @@ pub unsafe fn ykpiv_util_generate_key( && state.ver.major == 4 && (state.ver.minor < 3 || state.ver.minor == 3 && (state.ver.patch < 5)) { - let setting_name = CString::new(SZ_SETTING_ROCA).unwrap(); - setting_roca = setting_get_bool(setting_name.as_ptr(), true); + setting_roca = setting_get_bool(SZ_SETTING_ROCA, true); let psz_msg = match setting_roca.source { SettingSource::User => {