diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/src/lib.rs b/apps/desktop/desktop_native/windows_plugin_authenticator/src/lib.rs index 1f994a1e55e..1e8287ce4b4 100644 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/src/lib.rs +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/src/lib.rs @@ -2,6 +2,9 @@ #![allow(non_snake_case)] #![allow(non_camel_case_types)] +use std::ffi::OsString; +use std::os::windows::ffi::OsStrExt; + use std::ffi::c_uchar; use std::ffi::c_ulong; use std::ptr; @@ -38,14 +41,164 @@ pub fn register() -> std::result::Result<(), String> { util::message(String::from("About to call add_authenticator()")); let r = add_authenticator(); + //let r = add_authenticator_using_wide_encoding(); util::message(format!("added the authenticator: {:?}", r)); util::message(String::from("sleeping for 20 seconds...")); thread::sleep(Duration::from_millis(20000)); util::message(String::from("sleeping done")); + // // --------------------------------------- + // // ----- *** add test credential *** ----- + // // ----- using encode_utf16 ----- + // // --------------------------------------- + + // // Style 1, currently used: mem::forget + // let mut credential_id_string = String::from("32"); + // let credential_id_byte_count = credential_id_string.as_bytes().len() as c_ulong; + // let credential_id_pointer: *mut c_uchar = credential_id_string.as_mut_ptr(); + // std::mem::forget(credential_id_string); + + // // Style 2, experimental: Box::leak + // // Additionally, might need to Pin (same for style 1) + // // + // // let credential_id_string = String::from("32"); + // // let credential_id_byte_count = credential_id_string.as_bytes().len() as c_ulong; + // // let credential_id_box = Box::new(credential_id_string); + // // let credential_id_pointer: *mut c_uchar = credential_id_box.leak().as_mut_ptr(); + + // let mut rpid_string = String::from("webauthn.io"); + // let mut rpid_vec: Vec = rpid_string.encode_utf16().collect(); + // rpid_vec.push(0); + // let rpid: *mut u16 = rpid_vec.as_mut_ptr(); + // std::mem::forget(rpid_string); + // std::mem::forget(rpid_vec); + + // let mut rp_friendly_name_string = String::from("WebAuthn Website"); + // let mut rp_friendly_name_vec: Vec = rp_friendly_name_string.encode_utf16().collect(); + // rp_friendly_name_vec.push(0); + // let rp_friendly_name: *mut u16 = rp_friendly_name_vec.as_mut_ptr(); + // std::mem::forget(rp_friendly_name_string); + // std::mem::forget(rp_friendly_name_vec); + + // let mut user_id_string = String::from("14"); + // let user_id_byte_count = user_id_string.as_bytes().len() as c_ulong; + // let user_id_pointer: *mut c_uchar = user_id_string.as_mut_ptr(); + // std::mem::forget(user_id_string); + + // let mut user_name_string = String::from("webauthn.io username"); + // let mut user_name_vec: Vec = user_name_string.encode_utf16().collect(); + // user_name_vec.push(0); + // let user_name: *mut u16 = user_name_vec.as_mut_ptr(); + // std::mem::forget(user_name_string); + // std::mem::forget(user_name_vec); + + // let mut user_display_name_string = String::from("webauthn.io display name"); + // let mut user_display_name_vec: Vec = user_display_name_string.encode_utf16().collect(); + // user_display_name_vec.push(0); + // let user_display_name: *mut u16 = user_display_name_vec.as_mut_ptr(); + // std::mem::forget(user_display_name_string); + // std::mem::forget(user_display_name_vec); + + // let mut credential_details = ExperimentalWebAuthnPluginCredentialDetails { + // credential_id_byte_count, + // credential_id_pointer, + // rpid, + // rp_friendly_name, + // user_id_byte_count, + // user_id_pointer, + // user_name, + // user_display_name, + // }; + // let credential_details_ptr: *mut ExperimentalWebAuthnPluginCredentialDetails = + // &mut credential_details; + // std::mem::forget(credential_details); + + // let mut clsid_string = String::from(format!("{{{}}}", CLSID)); + // let mut clsid_vec: Vec = clsid_string.encode_utf16().collect(); + // clsid_vec.push(0); + // let plugin_clsid: *mut u16 = clsid_vec.as_mut_ptr(); + // std::mem::forget(clsid_string); + // std::mem::forget(clsid_vec); + + // let mut credentials: Vec<*mut ExperimentalWebAuthnPluginCredentialDetails> = + // vec![credential_details_ptr]; + // let credential_count: c_ulong = credentials.len() as c_ulong; + // let credentials_ptr: *mut *mut ExperimentalWebAuthnPluginCredentialDetails = + // credentials.as_mut_ptr(); + // std::mem::forget(credentials); + + // let mut credentials_details_list = ExperimentalWebAuthnPluginCredentialDetailsList { + // plugin_clsid, + // credential_count, + // credentials: credentials_ptr, + // }; + // let credentials_details_list_ptr: *mut ExperimentalWebAuthnPluginCredentialDetailsList = + // &mut credentials_details_list; + // std::mem::forget(credentials_details_list); + + // util::message(format!("about to link the fn pointer for add credentials")); + + // let result = unsafe { + // delay_load::( + // s!("webauthn.dll"), + // s!("EXPERIMENTAL_WebAuthNPluginAuthenticatorAddCredentials"), + // ) + // }; + + // util::message(format!("about to call add credentials")); + + // let result = match result { + // Some(api) => { + // let result = unsafe { api(credentials_details_list_ptr) }; + + // if result.is_err() { + // return Err(format!( + // "Error: Error response from EXPERIMENTAL_WebAuthNPluginAuthenticatorAddCredentials()\n{}", + // result.message() + // )); + // } + + // Ok(()) + // }, + // None => { + // Err(String::from("Error: Can't complete add_credentials(), as the function EXPERIMENTAL_WebAuthNPluginAuthenticatorAddCredentials can't be loaded.")) + // } + // }; + + // util::message(format!("add credentials attempt: {:?}", result)); + + // -------------------------------------------------------------------------------------------- + + // std::mem::forget(credential_id); + // let mut test_credential = ExperimentalWebAuthnPluginCredentialDetails::create( + // String::from("32"), + // String::from("webauthn.io"), + // String::from("WebAuthn Website"), + // String::from("14"), + // String::from("web user name"), + // String::from("web user display name"), + // ); + // let test_credential_ptr: *mut ExperimentalWebAuthnPluginCredentialDetails = &mut test_credential; + // //std::mem::forget(test_credential); + // let mut test_credential_list: Vec<*mut ExperimentalWebAuthnPluginCredentialDetails> = vec![test_credential_ptr]; + // let test_credential_list_ptr: *mut *mut ExperimentalWebAuthnPluginCredentialDetails = test_credential_list.as_mut_ptr(); + // let pluginclsid = String::from(CLSID).into_win_utf16().0; + + // let credentials = ExperimentalWebAuthnPluginCredentialDetailsList { + // plugin_clsid: pluginclsid, + // credential_count: 1, + // credentials: test_credential_list_ptr, + // }; + + // let r = add_credentials(credentials); + // util::message(format!("added the credentials: {:?}", r)); + + // -------------------------------------------------------------------------------------------- + // --------------------------------------- // ----- *** add test credential *** ----- + // ----- using encode_wide ----- // --------------------------------------- // Style 1, currently used: mem::forget @@ -54,26 +207,16 @@ pub fn register() -> std::result::Result<(), String> { let credential_id_pointer: *mut c_uchar = credential_id_string.as_mut_ptr(); std::mem::forget(credential_id_string); - // Style 2, experimental: Box::leak - // Additionally, might need to Pin (same for style 1) - // - // let credential_id_string = String::from("32"); - // let credential_id_byte_count = credential_id_string.as_bytes().len() as c_ulong; - // let credential_id_box = Box::new(credential_id_string); - // let credential_id_pointer: *mut c_uchar = credential_id_box.leak().as_mut_ptr(); - - let mut rpid_string = String::from("webauthn.io"); - let mut rpid_vec: Vec = rpid_string.encode_utf16().collect(); + let rpid_string = String::from("webauthn.io"); + let mut rpid_vec: Vec = OsString::from(rpid_string).encode_wide().collect(); rpid_vec.push(0); let rpid: *mut u16 = rpid_vec.as_mut_ptr(); - std::mem::forget(rpid_string); std::mem::forget(rpid_vec); - let mut rp_friendly_name_string = String::from("WebAuthn Website"); - let mut rp_friendly_name_vec: Vec = rp_friendly_name_string.encode_utf16().collect(); + let rp_friendly_name_string = String::from("WebAuthn Websitewide "); + let mut rp_friendly_name_vec: Vec = OsString::from(rp_friendly_name_string).encode_wide().collect(); rp_friendly_name_vec.push(0); let rp_friendly_name: *mut u16 = rp_friendly_name_vec.as_mut_ptr(); - std::mem::forget(rp_friendly_name_string); std::mem::forget(rp_friendly_name_vec); let mut user_id_string = String::from("14"); @@ -81,18 +224,16 @@ pub fn register() -> std::result::Result<(), String> { let user_id_pointer: *mut c_uchar = user_id_string.as_mut_ptr(); std::mem::forget(user_id_string); - let mut user_name_string = String::from("webauthn.io username"); - let mut user_name_vec: Vec = user_name_string.encode_utf16().collect(); + let user_name_string = String::from("webauthn.io wide username"); + let mut user_name_vec: Vec = OsString::from(user_name_string).encode_wide().collect(); user_name_vec.push(0); let user_name: *mut u16 = user_name_vec.as_mut_ptr(); - std::mem::forget(user_name_string); std::mem::forget(user_name_vec); - let mut user_display_name_string = String::from("webauthn.io display name"); - let mut user_display_name_vec: Vec = user_display_name_string.encode_utf16().collect(); + let user_display_name_string = String::from("webauthn.io wide display name"); + let mut user_display_name_vec: Vec = OsString::from(user_display_name_string).encode_wide().collect(); user_display_name_vec.push(0); let user_display_name: *mut u16 = user_display_name_vec.as_mut_ptr(); - std::mem::forget(user_display_name_string); std::mem::forget(user_display_name_vec); let mut credential_details = ExperimentalWebAuthnPluginCredentialDetails { @@ -109,11 +250,10 @@ pub fn register() -> std::result::Result<(), String> { &mut credential_details; std::mem::forget(credential_details); - let mut clsid_string = String::from(format!("{{{}}}", CLSID)); - let mut clsid_vec: Vec = clsid_string.encode_utf16().collect(); + let clsid_string = String::from(format!("{{{}}}", CLSID)); + let mut clsid_vec: Vec = OsString::from(clsid_string).encode_wide().collect(); clsid_vec.push(0); let plugin_clsid: *mut u16 = clsid_vec.as_mut_ptr(); - std::mem::forget(clsid_string); std::mem::forget(clsid_vec); let mut credentials: Vec<*mut ExperimentalWebAuthnPluginCredentialDetails> = @@ -163,29 +303,7 @@ pub fn register() -> std::result::Result<(), String> { util::message(format!("add credentials attempt: {:?}", result)); - // std::mem::forget(credential_id); - // let mut test_credential = ExperimentalWebAuthnPluginCredentialDetails::create( - // String::from("32"), - // String::from("webauthn.io"), - // String::from("WebAuthn Website"), - // String::from("14"), - // String::from("web user name"), - // String::from("web user display name"), - // ); - // let test_credential_ptr: *mut ExperimentalWebAuthnPluginCredentialDetails = &mut test_credential; - // //std::mem::forget(test_credential); - // let mut test_credential_list: Vec<*mut ExperimentalWebAuthnPluginCredentialDetails> = vec![test_credential_ptr]; - // let test_credential_list_ptr: *mut *mut ExperimentalWebAuthnPluginCredentialDetails = test_credential_list.as_mut_ptr(); - // let pluginclsid = String::from(CLSID).into_win_utf16().0; - - // let credentials = ExperimentalWebAuthnPluginCredentialDetailsList { - // plugin_clsid: pluginclsid, - // credential_count: 1, - // credentials: test_credential_list_ptr, - // }; - - // let r = add_credentials(credentials); - // util::message(format!("added the credentials: {:?}", r)); + // -------------------------------------------------------------------------------------------- Ok(()) } @@ -271,6 +389,74 @@ fn register_com_library() -> std::result::Result<(), String> { } } +// testing wide encoding +fn add_authenticator_using_wide_encoding() -> std::result::Result<(), String> { + // let (authenticator_name_pointer, authenticator_name_bytes) = String::from(AUTHENTICATOR_NAME).into_win_utf16_wide(); + let mut authenticator_name: Vec = OsString::from(AUTHENTICATOR_NAME).encode_wide().collect(); + //authenticator_name.push(0); + let authenticator_name_pointer = authenticator_name.as_mut_ptr(); + + // let (clsid_pointer, clsid_bytes) = String::from(CLSID).into_win_utf16_wide(); + let mut clsid: Vec = OsString::from(CLSID).encode_wide().collect(); + //clsid.push(0); + let clsid_pointer = clsid.as_mut_ptr(); + + // let (rpid_pointer, rpid_bytes) = String::from(RPID).into_win_utf16_wide(); + let mut rpid: Vec = OsString::from(RPID).encode_wide().collect(); + //rpid.push(0); + let rpid_pointer = rpid.as_mut_ptr(); + + // Example authenticator info blob + let cbor_authenticator_info = "A60182684649444F5F325F30684649444F5F325F310282637072666B686D61632D7365637265740350D548826E79B4DB40A3D811116F7E834904A362726BF5627570F5627576F5098168696E7465726E616C0A81A263616C672664747970656A7075626C69632D6B6579"; + let mut authenticator_info_bytes = hex::decode(cbor_authenticator_info).unwrap(); + + let add_authenticator_options = webauthn::ExperimentalWebAuthnPluginAddAuthenticatorOptions { + authenticator_name: authenticator_name_pointer, + plugin_clsid: clsid_pointer, + rpid: rpid_pointer, + light_theme_logo: ptr::null(), + dark_theme_logo: ptr::null(), + cbor_authenticator_info_byte_count: authenticator_info_bytes.len() as u32, + cbor_authenticator_info: authenticator_info_bytes.as_mut_ptr(), + }; + + let plugin_signing_public_key_byte_count: u32 = 0; + let mut plugin_signing_public_key: c_uchar = 0; + let plugin_signing_public_key_ptr = &mut plugin_signing_public_key; + + let mut add_response = webauthn::ExperimentalWebAuthnPluginAddAuthenticatorResponse { + plugin_operation_signing_key_byte_count: plugin_signing_public_key_byte_count, + plugin_operation_signing_key: plugin_signing_public_key_ptr, + }; + let mut add_response_ptr: *mut webauthn::ExperimentalWebAuthnPluginAddAuthenticatorResponse = + &mut add_response; + + let result = unsafe { + delay_load::( + s!("webauthn.dll"), + s!("EXPERIMENTAL_WebAuthNPluginAddAuthenticator"), + ) + }; + + match result { + Some(api) => { + let result = unsafe { api(&add_authenticator_options, &mut add_response_ptr) }; + + if result.is_err() { + return Err(format!( + "Error: Error response from EXPERIMENTAL_WebAuthNPluginAddAuthenticator()\n{}", + result.message() + )); + } + + Ok(()) + }, + None => { + Err(String::from("Error: Can't complete add_authenticator(), as the function EXPERIMENTAL_WebAuthNPluginAddAuthenticator can't be found.")) + } + } +} + /// Adds Bitwarden as a plugin authenticator. fn add_authenticator() -> std::result::Result<(), String> { let authenticator_name: HSTRING = AUTHENTICATOR_NAME.into(); @@ -293,8 +479,8 @@ fn add_authenticator() -> std::result::Result<(), String> { authenticator_name: authenticator_name_ptr, plugin_clsid: clsid_ptr, rpid: relying_party_id_ptr, - light_theme_logo: ptr::null(), // unused by Windows - dark_theme_logo: ptr::null(), // unused by Windows + light_theme_logo: ptr::null(), + dark_theme_logo: ptr::null(), cbor_authenticator_info_byte_count: authenticator_info_bytes.len() as u32, cbor_authenticator_info: authenticator_info_bytes.as_mut_ptr(), }; diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/src/pluginauthenticator.rs b/apps/desktop/desktop_native/windows_plugin_authenticator/src/pluginauthenticator.rs index ad4296435e6..6cc08a6ac2f 100644 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/src/pluginauthenticator.rs +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/src/pluginauthenticator.rs @@ -12,7 +12,7 @@ */ use windows::Win32::System::Com::*; -use windows::{Foundation::*, Win32::System::Com::*}; +//use windows::{Foundation::*, Win32::System::Com::*}; use windows_core::*; use crate::util; diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/src/util.rs b/apps/desktop/desktop_native/windows_plugin_authenticator/src/util.rs index ae68ca63bca..b1f41564322 100644 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/src/util.rs +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/src/util.rs @@ -1,3 +1,6 @@ +use std::ffi::OsString; +use std::os::windows::ffi::OsStrExt; + use serde_json::json; use windows::Win32::Foundation::*; use windows::Win32::System::LibraryLoader::*; @@ -24,6 +27,7 @@ pub unsafe fn delay_load(library: PCSTR, function: PCSTR) -> Option { pub trait WindowsString { fn into_win_utf8(self: Self) -> (*mut u8, u32); fn into_win_utf16(self: Self) -> (*mut u16, u32); + fn into_win_utf16_wide(self: Self) -> (*mut u16, u32); } impl WindowsString for String { @@ -40,6 +44,13 @@ impl WindowsString for String { (v.as_mut_ptr(), v.len() as u32) } + + fn into_win_utf16_wide(self: Self) -> (*mut u16, u32) { + let mut v: Vec = OsString::from(self).encode_wide().collect(); + v.push(0); + + (v.as_mut_ptr(), v.len() as u32) + } } pub fn message(message: String) {