summaryrefslogtreecommitdiffstats
path: root/src/tools/cargo/credential/cargo-credential-wincred
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /src/tools/cargo/credential/cargo-credential-wincred
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz
rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.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')
-rw-r--r--src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml6
-rw-r--r--src/tools/cargo/credential/cargo-credential-wincred/src/lib.rs125
-rw-r--r--src/tools/cargo/credential/cargo-credential-wincred/src/main.rs122
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);
-}