#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
use std::os::raw::c_char;
use std::ffi::CStr;
use std::ffi::CString;
extern "C" {
fn get_username_for_realm_c(realm: *const c_char) -> *const c_char;
fn free_char_array_c(char_array: *const c_char);
fn has_credentials_c() -> i32;
fn has_credentials_for_realm_c(realm: *const c_char) -> i32;
}
fn c_string_from_string(string: String) -> Result<CString, String> {
match CString::new(string) {
Ok(c_string) => Ok(c_string),
Err(error) => Err(format!("Failed to encode String as CString: {:?}", error)),
}
}
fn string_from_char_ptr(char_array: *const c_char) -> Result<String, String> {
if char_array.is_null() {
return Err(String::from("Attempted to convert a NULL string value to a String."));
}
let c_string = unsafe { CStr::from_ptr(char_array) };
let string = c_string.to_owned().into_string();
unsafe { free_char_array_c(char_array) };
match string {
Ok(result) => Ok(result),
Err(error) => Err(format!("Failed to decode char array: {:?}", error)),
}
}
pub fn get_username_for_realm(realm: String) -> Result<Option<String>, String> {
let realm = c_string_from_string(realm)?;
let username = unsafe { get_username_for_realm_c(realm.as_ptr()) };
if username.is_null() {
Ok(None)
} else {
match string_from_char_ptr(username) {
Ok(result) => Ok(Some(result)),
Err(error) => Err(error),
}
}
}
pub fn has_credentials() -> bool {
unsafe { has_credentials_c() == 1 }
}
pub fn has_credentials_for_realm(realm: String) -> Result<bool, String> {
let realm = c_string_from_string(realm)?;
Ok(unsafe { has_credentials_for_realm_c(realm.as_ptr()) == 1 })
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
#[test]
fn test_has_credentials() {
if has_credentials() {
println!("Successfully checked for valid credentials.");
} else {
println!("Successfully checked for no valid credentials.");
}
}
#[test]
fn test_has_credentials_for_realm() {
let realm = match env::var("REALM") {
Ok(realm) => realm,
_ => {
println!("No realm specified.");
return;
},
};
assert_eq!(has_credentials_for_realm(realm), Ok(true));
println!("Successfully checked credentials.");
}
#[test]
fn fail_has_credentials_for_realm() {
assert_eq!(has_credentials_for_realm(String::from("EXAMPLE.COM")), Ok(false));
println!("Successfully determined no authentication.");
}
#[test]
fn test_get_username() {
let (realm, username) = match (env::var("REALM"), env::var("KUSER")) {
(Ok(r), Ok(u)) => (r, u),
(_, _) => {
println!("No realm and username specified.");
return;
},
};
assert_eq!(get_username_for_realm(realm).unwrap(), Some(username));
println!("Successfully determined username.");
}
#[test]
fn fail_get_username() {
assert_eq!(get_username_for_realm(String::from("EXAMPLE.COM")).unwrap(), None);
println!("Successfully determined no username.");
}
}