diff --git a/.github/workflows/cicd.yaml b/.github/workflows/cicd.yaml index 21be196..370668c 100644 --- a/.github/workflows/cicd.yaml +++ b/.github/workflows/cicd.yaml @@ -86,12 +86,63 @@ jobs: path: build/WindowsHelloBridge.exe if-no-files-found: error + build-pam-module-aarch64: + name: "Build PAM module (AArch64)" + + runs-on: ubuntu-24.04-arm + + permissions: + contents: read + + steps: + - uses: actions/checkout@v3 + + - name: Enable Rust cache + uses: Swatinem/rust-cache@v2 + + - name: Install libpam + run: sudo apt-get install libpam0g-dev + + - name: Build + run: make clean build/pam_wsl_hello.so + + - uses: actions/upload-artifact@v4 + name: Upload artifact + with: + name: "PAM module AArch64" + path: build/pam_wsl_hello.so + if-no-files-found: error + + build-windows-binary-aarch64: + name: "Build Windows binary (AArch64)" + + runs-on: windows-11-arm + + permissions: + contents: read + + steps: + - uses: actions/checkout@v3 + + - name: Enable Rust cache + uses: Swatinem/rust-cache@v2 + + - name: Build + run: make clean build/WindowsHelloBridge.exe + + - uses: actions/upload-artifact@v4 + name: Upload artifacts + with: + name: "Windows Binary AArch64" + path: build/WindowsHelloBridge.exe + if-no-files-found: error + release: name: "Release" runs-on: ubuntu-latest - needs: [build-pam-module, build-windows-binary] + needs: [build-pam-module, build-windows-binary, build-pam-module-aarch64, build-windows-binary-aarch64] steps: - uses: actions/checkout@v3 @@ -106,6 +157,16 @@ jobs: name: "PAM module" path: build + - uses: actions/download-artifact@v4 + with: + name: "Windows Binary AArch64" + path: build-aarch64 + + - uses: actions/download-artifact@v4 + with: + name: "PAM module AArch64" + path: build-aarch64 + - name: Conventional Changelog Action if: ${{ github.event.inputs.should_publish == 'yes' }} id: changelog @@ -119,13 +180,17 @@ jobs: git-user-email: "41898282+github-actions[bot]@users.noreply.github.com" release-count: "0" - - name: Create Release asset + - name: Create Release assets id: create_asset - env: - release_name: release run: | - make -d release RELEASE="$release_name" - echo "release_asset=$release_name.tar.gz" >> $GITHUB_OUTPUT + make -d release RELEASE="release" + echo "release_asset=release.tar.gz" >> $GITHUB_OUTPUT + mkdir -p release-aarch64/build + cp build-aarch64/pam_wsl_hello.so release-aarch64/build/ + cp build-aarch64/WindowsHelloBridge.exe release-aarch64/build/ + cp install.sh pam-config release-aarch64/ + tar cvzf release-aarch64.tar.gz release-aarch64 + echo "release_asset_aarch64=release-aarch64.tar.gz" >> $GITHUB_OUTPUT - uses: actions/upload-artifact@v4 if: ${{ github.event.inputs.should_publish != 'yes' }} @@ -135,6 +200,14 @@ jobs: path: ${{ steps.create_asset.outputs.release_asset }} if-no-files-found: error + - uses: actions/upload-artifact@v4 + if: ${{ github.event.inputs.should_publish != 'yes' }} + name: Upload the AArch64 release asset (CI) + with: + name: ${{ steps.create_asset.outputs.release_asset_aarch64 }} + path: ${{ steps.create_asset.outputs.release_asset_aarch64 }} + if-no-files-found: error + - name: Create Release if: ${{ github.event.inputs.should_publish == 'yes' }} id: create_release @@ -157,3 +230,15 @@ jobs: asset_path: ${{ steps.create_asset.outputs.release_asset }} asset_name: ${{ steps.create_asset.outputs.release_asset }} asset_content_type: application/gzip + + - name: Upload Release Asset AArch64 + if: ${{ github.event.inputs.should_publish == 'yes' }} + id: upload-release-asset-aarch64 + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ${{ steps.create_asset.outputs.release_asset_aarch64 }} + asset_name: ${{ steps.create_asset.outputs.release_asset_aarch64 }} + asset_content_type: application/gzip diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6ef0a8d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,341 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "cc" +version = "1.2.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "libc" +version = "0.2.182" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "openssl" +version = "0.10.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-src" +version = "300.5.5+3.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f1787d533e03597a7934fd0a765f0d28e94ecc5fb7789f8053b1e699a56f709" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc", + "rand 0.4.6", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "uuid" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22" +dependencies = [ + "rand 0.3.23", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "win_hello_bridge" +version = "3.0.0" +dependencies = [ + "windows", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" + +[[package]] +name = "windows_i686_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" + +[[package]] +name = "windows_i686_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" + +[[package]] +name = "wsl_hello_pam" +version = "3.0.0" +dependencies = [ + "libc", + "openssl", + "toml", + "uuid", +] diff --git a/Cargo.toml b/Cargo.toml index 8f76d29..593fcfe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ members = [ [profile.release] lto = true +strip = "symbols" diff --git a/Makefile b/Makefile index 3353f3c..f6fb63d 100644 --- a/Makefile +++ b/Makefile @@ -9,13 +9,11 @@ all: build/pam_wsl_hello.so build/WindowsHelloBridge.exe build/pam_wsl_hello.so: | build # Build the PAM lib from Linux cargo build --release -p wsl_hello_pam - strip target/release/libpam_wsl_hello.so cp ./target/release/libpam_wsl_hello.so build/pam_wsl_hello.so build/WindowsHelloBridge.exe: | build # Build the authenticator from Windows $(WIN_CARGO) build -p win_hello_bridge --release - strip target/release/WindowsHelloBridge.exe cp ./target/release/WindowsHelloBridge.exe ./build build: diff --git a/win_hello_bridge/Cargo.toml b/win_hello_bridge/Cargo.toml index 53d5629..258e216 100644 --- a/win_hello_bridge/Cargo.toml +++ b/win_hello_bridge/Cargo.toml @@ -11,4 +11,4 @@ name = "WindowsHelloBridge" path = "src/main.rs" [dependencies] -windows = { version = "0.32", features = ["alloc", "Foundation", "Security_Credentials", "Security_Cryptography", "Storage_Streams", "UI_Popups", "Win32_Foundation", "Win32_UI_WindowsAndMessaging"] } \ No newline at end of file +windows = { version = "0.39", features = ["Foundation", "Security_Credentials", "Security_Cryptography", "Storage_Streams", "UI_Popups", "Win32_Foundation", "Win32_UI_WindowsAndMessaging"] } \ No newline at end of file diff --git a/win_hello_bridge/src/authenticator.rs b/win_hello_bridge/src/authenticator.rs index 8264807..c7e7c7d 100644 --- a/win_hello_bridge/src/authenticator.rs +++ b/win_hello_bridge/src/authenticator.rs @@ -3,16 +3,14 @@ use std::sync::mpsc; use std::time::Duration; use windows::{ Security::{Credentials::KeyCredentialManager, Cryptography::CryptographicBuffer}, - Win32::{ - Foundation::PWSTR, - UI::WindowsAndMessaging::{FindWindowW, SetForegroundWindow}, - }, + Win32::UI::WindowsAndMessaging::{FindWindowW, SetForegroundWindow}, UI::Popups::MessageDialog, + core::{HSTRING, PCWSTR}, }; pub(crate) fn verify_user(key_name: &str, data_to_sign: &[u8]) -> Result, FailureReason> { if !KeyCredentialManager::IsSupportedAsync()?.get()? { - let _ = MessageDialog::Create("Windows Hello not supported")? + let _ = MessageDialog::Create(&HSTRING::from("Windows Hello not supported"))? .ShowAsync()? .get(); @@ -20,7 +18,7 @@ pub(crate) fn verify_user(key_name: &str, data_to_sign: &[u8]) -> Result } let key = { - let result = KeyCredentialManager::OpenAsync(key_name)?.get()?; + let result = KeyCredentialManager::OpenAsync(&HSTRING::from(key_name))?.get()?; FailureReason::from_credential_status(result.Status()?, key_name)?; result.Credential()? }; @@ -37,7 +35,7 @@ pub(crate) fn verify_user(key_name: &str, data_to_sign: &[u8]) -> Result let buffer = result.Result()?; let mut out = windows::core::Array::::with_len(buffer.Length().unwrap() as usize); - CryptographicBuffer::CopyToByteArray(buffer, &mut out)?; + CryptographicBuffer::CopyToByteArray(&buffer, &mut out)?; Ok(out.to_vec()) } @@ -47,10 +45,10 @@ fn focus_hello_window() -> mpsc::SyncSender<()> { std::thread::spawn(move || { let hwnd = loop { - let hwnd = - unsafe { FindWindowW("Credential Dialog Xaml Host", PWSTR(core::ptr::null_mut())) }; + let class_name = HSTRING::from("Credential Dialog Xaml Host"); + let hwnd = unsafe { FindWindowW(&class_name, PCWSTR::null()) }; - if let Ok(hwnd) = hwnd.ok() { + if hwnd.0 != 0 { break hwnd; } diff --git a/win_hello_bridge/src/creator.rs b/win_hello_bridge/src/creator.rs index ce93d3c..a5f9992 100644 --- a/win_hello_bridge/src/creator.rs +++ b/win_hello_bridge/src/creator.rs @@ -1,13 +1,16 @@ use crate::FailureReason; -use windows::Security::{ - Credentials::{KeyCredentialCreationOption, KeyCredentialManager}, - Cryptography::CryptographicBuffer, +use windows::{ + core::HSTRING, + Security::{ + Credentials::{KeyCredentialCreationOption, KeyCredentialManager}, + Cryptography::CryptographicBuffer, + }, }; pub(crate) fn create_public_key(key_name: &str) -> Result { let public_key = { let result = KeyCredentialManager::RequestCreateAsync( - key_name, + &HSTRING::from(key_name), KeyCredentialCreationOption::FailIfExists, )? .get()?; @@ -17,7 +20,7 @@ pub(crate) fn create_public_key(key_name: &str) -> Result .Credential()? .RetrievePublicKeyWithDefaultBlobType()?, Err(FailureReason::CredentialExists) => { - let result = KeyCredentialManager::OpenAsync(key_name)?.get()?; + let result = KeyCredentialManager::OpenAsync(&HSTRING::from(key_name))?.get()?; FailureReason::from_credential_status(result.Status()?, key_name)?; result .Credential()? @@ -29,6 +32,6 @@ pub(crate) fn create_public_key(key_name: &str) -> Result Ok(format!( "-----BEGIN PUBLIC KEY-----\n{}\n-----END PUBLIC KEY-----\n", - CryptographicBuffer::EncodeToBase64String(public_key)? + CryptographicBuffer::EncodeToBase64String(&public_key)? )) } diff --git a/wsl_hello_pam/src/auth.rs b/wsl_hello_pam/src/auth.rs index 00a8e64..06e2d76 100644 --- a/wsl_hello_pam/src/auth.rs +++ b/wsl_hello_pam/src/auth.rs @@ -41,7 +41,7 @@ pub fn pam_sm_authenticate( }) } -fn get_user(pamh: *mut pam_handle_t, prompt: Option<&str>) -> Result, i32> { +fn get_user(pamh: *mut pam_handle_t, prompt: Option<&str>) -> Result, i32> { let mut c_user: *const c_char = ptr::null(); let tmp_prompt_str: CString; let c_prompt = match prompt {