-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(cred): Move win impl to inline mod
- Loading branch information
Showing
1 changed file
with
94 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,111 +1,116 @@ | ||
//! Cargo registry windows credential process. | ||
|
||
use cargo_credential::{Credential, Error}; | ||
use std::ffi::OsStr; | ||
use std::os::windows::ffi::OsStrExt; | ||
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; | ||
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; | ||
|
||
struct WindowsCredential; | ||
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"); | ||
/// 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 | ||
} | ||
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 target_name(registry_name: &str) -> Vec<u16> { | ||
wstr(&format!("cargo-registry:{}", registry_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(), | ||
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()) | ||
} | ||
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()); | ||
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(()) | ||
} | ||
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(()); | ||
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()); | ||
} | ||
return Err(format!("failed to remove token: {}", err).into()); | ||
Ok(()) | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
fn main() { | ||
cargo_credential::main(WindowsCredential); | ||
cargo_credential::main(win::WindowsCredential); | ||
} |