diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:24 +0000 |
commit | 023939b627b7dc93b01471f7d41fb8553ddb4ffa (patch) | |
tree | 60fc59477c605c72b0a1051409062ddecc43f877 /src/tools/cargo/credential/cargo-credential-wincred | |
parent | Adding debian version 1.72.1+dfsg1-1. (diff) | |
download | rustc-023939b627b7dc93b01471f7d41fb8553ddb4ffa.tar.xz rustc-023939b627b7dc93b01471f7d41fb8553ddb4ffa.zip |
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/cargo/credential/cargo-credential-wincred')
3 files changed, 128 insertions, 125 deletions
diff --git a/src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml b/src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml index cd168a8a3..8c609dc4e 100644 --- a/src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml +++ b/src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "cargo-credential-wincred" -version = "0.2.0" -edition = "2021" -license = "MIT OR Apache-2.0" +version = "0.3.0" +edition.workspace = true +license.workspace = true repository = "https://github.com/rust-lang/cargo" description = "A Cargo credential process that stores tokens with Windows Credential Manager." diff --git a/src/tools/cargo/credential/cargo-credential-wincred/src/lib.rs b/src/tools/cargo/credential/cargo-credential-wincred/src/lib.rs new file mode 100644 index 000000000..9200ca58f --- /dev/null +++ b/src/tools/cargo/credential/cargo-credential-wincred/src/lib.rs @@ -0,0 +1,125 @@ +//! Cargo registry windows credential process. + +#[cfg(windows)] +mod win { + use cargo_credential::{read_token, Action, CacheControl, CredentialResponse, RegistryInfo}; + use cargo_credential::{Credential, Error}; + use std::ffi::OsStr; + + use std::os::windows::ffi::OsStrExt; + + use windows_sys::core::PWSTR; + use windows_sys::Win32::Foundation::ERROR_NOT_FOUND; + use windows_sys::Win32::Foundation::FILETIME; + use windows_sys::Win32::Foundation::TRUE; + use windows_sys::Win32::Security::Credentials::CredReadW; + use windows_sys::Win32::Security::Credentials::CredWriteW; + use windows_sys::Win32::Security::Credentials::CREDENTIALW; + use windows_sys::Win32::Security::Credentials::CRED_PERSIST_LOCAL_MACHINE; + use windows_sys::Win32::Security::Credentials::CRED_TYPE_GENERIC; + use windows_sys::Win32::Security::Credentials::{CredDeleteW, CredFree}; + + pub struct WindowsCredential; + + /// Converts a string to a nul-terminated wide UTF-16 byte sequence. + fn wstr(s: &str) -> Vec<u16> { + let mut wide: Vec<u16> = OsStr::new(s).encode_wide().collect(); + if wide.iter().any(|b| *b == 0) { + panic!("nul byte in wide string"); + } + wide.push(0); + wide + } + + fn target_name(index_url: &str) -> Vec<u16> { + wstr(&format!("cargo-registry:{}", index_url)) + } + + impl Credential for WindowsCredential { + fn perform( + &self, + registry: &RegistryInfo, + action: &Action, + _args: &[&str], + ) -> Result<CredentialResponse, Error> { + match action { + Action::Get(_) => { + let target_name = target_name(registry.index_url); + let mut p_credential: *mut CREDENTIALW = std::ptr::null_mut() as *mut _; + let bytes = unsafe { + if CredReadW( + target_name.as_ptr(), + CRED_TYPE_GENERIC, + 0, + &mut p_credential as *mut _, + ) != TRUE + { + let err = std::io::Error::last_os_error(); + if err.raw_os_error() == Some(ERROR_NOT_FOUND as i32) { + return Err(Error::NotFound); + } + return Err(Box::new(err).into()); + } + std::slice::from_raw_parts( + (*p_credential).CredentialBlob, + (*p_credential).CredentialBlobSize as usize, + ) + }; + let token = String::from_utf8(bytes.to_vec()).map_err(Box::new); + unsafe { CredFree(p_credential as *mut _) }; + Ok(CredentialResponse::Get { + token: token?.into(), + cache: CacheControl::Session, + operation_independent: true, + }) + } + Action::Login(options) => { + let token = read_token(options, registry)?.expose(); + let target_name = target_name(registry.index_url); + let comment = wstr("Cargo registry token"); + let credential = CREDENTIALW { + Flags: 0, + Type: CRED_TYPE_GENERIC, + TargetName: target_name.as_ptr() as PWSTR, + Comment: comment.as_ptr() as PWSTR, + LastWritten: FILETIME { + dwLowDateTime: 0, + dwHighDateTime: 0, + }, + CredentialBlobSize: token.len() as u32, + CredentialBlob: token.as_bytes().as_ptr() as *mut u8, + Persist: CRED_PERSIST_LOCAL_MACHINE, + AttributeCount: 0, + Attributes: std::ptr::null_mut(), + TargetAlias: std::ptr::null_mut(), + UserName: std::ptr::null_mut(), + }; + let result = unsafe { CredWriteW(&credential, 0) }; + if result != TRUE { + let err = std::io::Error::last_os_error(); + return Err(Box::new(err).into()); + } + Ok(CredentialResponse::Login) + } + Action::Logout => { + let target_name = target_name(registry.index_url); + let result = unsafe { CredDeleteW(target_name.as_ptr(), CRED_TYPE_GENERIC, 0) }; + if result != TRUE { + let err = std::io::Error::last_os_error(); + if err.raw_os_error() == Some(ERROR_NOT_FOUND as i32) { + return Err(Error::NotFound); + } + return Err(Box::new(err).into()); + } + Ok(CredentialResponse::Logout) + } + _ => Err(Error::OperationNotSupported), + } + } + } +} + +#[cfg(not(windows))] +pub use cargo_credential::UnsupportedCredential as WindowsCredential; +#[cfg(windows)] +pub use win::WindowsCredential; diff --git a/src/tools/cargo/credential/cargo-credential-wincred/src/main.rs b/src/tools/cargo/credential/cargo-credential-wincred/src/main.rs deleted file mode 100644 index 4377172e8..000000000 --- a/src/tools/cargo/credential/cargo-credential-wincred/src/main.rs +++ /dev/null @@ -1,122 +0,0 @@ -//! Cargo registry windows credential process. - -#[cfg(windows)] -mod win { - use cargo_credential::{Credential, Error}; - use std::ffi::OsStr; - use std::os::windows::ffi::OsStrExt; - - use windows_sys::core::PWSTR; - use windows_sys::Win32::Foundation::ERROR_NOT_FOUND; - use windows_sys::Win32::Foundation::FILETIME; - use windows_sys::Win32::Foundation::TRUE; - use windows_sys::Win32::Security::Credentials::CredDeleteW; - use windows_sys::Win32::Security::Credentials::CredReadW; - use windows_sys::Win32::Security::Credentials::CredWriteW; - use windows_sys::Win32::Security::Credentials::CREDENTIALW; - use windows_sys::Win32::Security::Credentials::CRED_PERSIST_LOCAL_MACHINE; - use windows_sys::Win32::Security::Credentials::CRED_TYPE_GENERIC; - - pub(crate) struct WindowsCredential; - - /// Converts a string to a nul-terminated wide UTF-16 byte sequence. - fn wstr(s: &str) -> Vec<u16> { - let mut wide: Vec<u16> = OsStr::new(s).encode_wide().collect(); - if wide.iter().any(|b| *b == 0) { - panic!("nul byte in wide string"); - } - wide.push(0); - wide - } - - fn target_name(registry_name: &str) -> Vec<u16> { - wstr(&format!("cargo-registry:{}", registry_name)) - } - - impl Credential for WindowsCredential { - fn name(&self) -> &'static str { - env!("CARGO_PKG_NAME") - } - - fn get(&self, index_url: &str) -> Result<String, Error> { - let target_name = target_name(index_url); - let p_credential: *mut CREDENTIALW = std::ptr::null_mut() as *mut _; - unsafe { - if CredReadW( - target_name.as_ptr(), - CRED_TYPE_GENERIC, - 0, - p_credential as *mut _ as *mut _, - ) != TRUE - { - return Err(format!( - "failed to fetch token: {}", - std::io::Error::last_os_error() - ) - .into()); - } - let bytes = std::slice::from_raw_parts( - (*p_credential).CredentialBlob, - (*p_credential).CredentialBlobSize as usize, - ); - String::from_utf8(bytes.to_vec()) - .map_err(|_| "failed to convert token to UTF8".into()) - } - } - - fn store(&self, index_url: &str, token: &str, name: Option<&str>) -> Result<(), Error> { - let token = token.as_bytes(); - let target_name = target_name(index_url); - let comment = match name { - Some(name) => wstr(&format!("Cargo registry token for {}", name)), - None => wstr("Cargo registry token"), - }; - let mut credential = CREDENTIALW { - Flags: 0, - Type: CRED_TYPE_GENERIC, - TargetName: target_name.as_ptr() as PWSTR, - Comment: comment.as_ptr() as PWSTR, - LastWritten: FILETIME { - dwLowDateTime: 0, - dwHighDateTime: 0, - }, - CredentialBlobSize: token.len() as u32, - CredentialBlob: token.as_ptr() as *mut u8, - Persist: CRED_PERSIST_LOCAL_MACHINE, - AttributeCount: 0, - Attributes: std::ptr::null_mut(), - TargetAlias: std::ptr::null_mut(), - UserName: std::ptr::null_mut(), - }; - let result = unsafe { CredWriteW(&mut credential, 0) }; - if result != TRUE { - let err = std::io::Error::last_os_error(); - return Err(format!("failed to store token: {}", err).into()); - } - Ok(()) - } - - fn erase(&self, index_url: &str) -> Result<(), Error> { - let target_name = target_name(index_url); - let result = unsafe { CredDeleteW(target_name.as_ptr(), CRED_TYPE_GENERIC, 0) }; - if result != TRUE { - let err = std::io::Error::last_os_error(); - if err.raw_os_error() == Some(ERROR_NOT_FOUND as i32) { - eprintln!("not currently logged in to `{}`", index_url); - return Ok(()); - } - return Err(format!("failed to remove token: {}", err).into()); - } - Ok(()) - } - } -} - -#[cfg(not(windows))] -use cargo_credential::UnsupportedCredential as WindowsCredential; -#[cfg(windows)] -use win::WindowsCredential; - -fn main() { - cargo_credential::main(WindowsCredential); -} |