+38
-102
@@ -30,17 +30,14 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// 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 crate::consts::*;
|
||||||
use des::{
|
use des::{
|
||||||
block_cipher_trait::{generic_array::GenericArray, BlockCipher},
|
block_cipher_trait::{generic_array::GenericArray, BlockCipher},
|
||||||
TdesEde3,
|
TdesEde3,
|
||||||
};
|
};
|
||||||
use libc::{c_char, c_int, fclose, feof, fgets, fopen, getenv, sscanf, strcasecmp, strcmp};
|
use std::env;
|
||||||
use std::ffi::{CStr, CString};
|
use std::fs::File;
|
||||||
|
use std::io::{BufRead, BufReader};
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
/// 3DES keys. The three subkeys are concatenated.
|
/// 3DES keys. The three subkeys are concatenated.
|
||||||
@@ -50,10 +47,6 @@ impl DesKey {
|
|||||||
pub fn from_bytes(bytes: [u8; DES_LEN_3DES]) -> Self {
|
pub fn from_bytes(bytes: [u8; DES_LEN_3DES]) -> Self {
|
||||||
DesKey(bytes)
|
DesKey(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&self, out: &mut [u8]) {
|
|
||||||
out.copy_from_slice(&self.0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRef<[u8; 24]> for DesKey {
|
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
|
/// %T Security for Computer Networks
|
||||||
/// %I John Wiley & Sons
|
/// %I John Wiley & Sons
|
||||||
/// %D 1984
|
/// %D 1984
|
||||||
const weak_keys: [[u8; DES_LEN_DES]; 16] = [
|
const WEAK_KEYS: [[u8; DES_LEN_DES]; 16] = [
|
||||||
// weak keys
|
// weak keys
|
||||||
[0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01],
|
[0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01],
|
||||||
[0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE],
|
[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
|
// check odd parity key against table by DES key block
|
||||||
let mut rv = false;
|
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]
|
if weak_key == &tmp[0..DES_LEN_DES]
|
||||||
|| weak_key == &tmp[DES_LEN_DES..2 * DES_LEN_DES]
|
|| weak_key == &tmp[DES_LEN_DES..2 * DES_LEN_DES]
|
||||||
|| weak_key == &tmp[2 * DES_LEN_DES..3 * 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
|
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
|
/// Source of how a setting was configured
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum SettingSource {
|
pub enum SettingSource {
|
||||||
@@ -190,105 +166,65 @@ pub struct SettingBool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get a boolean config value
|
/// 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 {
|
let mut setting: SettingBool = SettingBool {
|
||||||
value: false,
|
value: false,
|
||||||
source: SettingSource::Default,
|
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(
|
if let Ok(f) = File::open("/etc/yubico/yubikeypiv.conf") {
|
||||||
b"/etc/yubico/yubikeypiv.conf\0".as_ptr() as *const c_char,
|
for line in BufReader::new(f).lines() {
|
||||||
b"r\0".as_ptr() as *const c_char,
|
let line = match line {
|
||||||
);
|
Ok(line) => line,
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
|
||||||
if pf.is_null() {
|
if line.starts_with('#') || line.starts_with('\r') || line.starts_with('\n') {
|
||||||
return setting;
|
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
|
setting
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a setting boolean from an environment variable
|
/// 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 {
|
let mut setting: SettingBool = SettingBool {
|
||||||
value: false,
|
value: false,
|
||||||
source: SettingSource::Default,
|
source: SettingSource::Default,
|
||||||
};
|
};
|
||||||
|
|
||||||
let sz_name = CString::new(format!(
|
if let Ok(value) = env::var(format!("YUBIKEY_PIV_{}", key)) {
|
||||||
"YUBIKEY_PIV_{}",
|
|
||||||
CStr::from_ptr(sz_setting).to_string_lossy()
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let psz_value = getenv(sz_name.as_ptr());
|
|
||||||
|
|
||||||
if !psz_value.is_null() {
|
|
||||||
setting.source = SettingSource::User;
|
setting.source = SettingSource::User;
|
||||||
setting.value = strcmp(psz_value, b"1\0".as_ptr() as *const c_char) == 0
|
setting.value = value == "1" || value == "true";
|
||||||
|| strcasecmp(psz_value, b"true\0".as_ptr() as *const c_char) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setting
|
setting
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a setting boolean
|
/// Get a setting boolean
|
||||||
pub unsafe fn setting_get_bool(sz_setting: *const c_char, def: bool) -> SettingBool {
|
pub fn setting_get_bool(key: &str, def: bool) -> SettingBool {
|
||||||
let mut setting = _get_bool_config(sz_setting);
|
let mut setting = _get_bool_config(key);
|
||||||
|
|
||||||
if setting.source == SettingSource::Default {
|
if setting.source == SettingSource::Default {
|
||||||
setting = _get_bool_env(sz_setting);
|
setting = _get_bool_env(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if setting.source == SettingSource::Default {
|
if setting.source == SettingSource::Default {
|
||||||
|
|||||||
+2
-3
@@ -41,7 +41,7 @@ use log::{error, warn};
|
|||||||
use pbkdf2::pbkdf2;
|
use pbkdf2::pbkdf2;
|
||||||
use sha1::Sha1;
|
use sha1::Sha1;
|
||||||
use std::ops::DerefMut;
|
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};
|
use zeroize::{Zeroize, Zeroizing};
|
||||||
|
|
||||||
/// Cardholder Unique Identifier (CHUID) Template
|
/// Cardholder Unique Identifier (CHUID) Template
|
||||||
@@ -1002,8 +1002,7 @@ pub unsafe fn ykpiv_util_generate_key(
|
|||||||
&& state.ver.major == 4
|
&& state.ver.major == 4
|
||||||
&& (state.ver.minor < 3 || state.ver.minor == 3 && (state.ver.patch < 5))
|
&& (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(SZ_SETTING_ROCA, true);
|
||||||
setting_roca = setting_get_bool(setting_name.as_ptr(), true);
|
|
||||||
|
|
||||||
let psz_msg = match setting_roca.source {
|
let psz_msg = match setting_roca.source {
|
||||||
SettingSource::User => {
|
SettingSource::User => {
|
||||||
|
|||||||
Reference in New Issue
Block a user