use std::io;
use std::mem;
use windows_sys::Win32::Foundation;
use windows_sys::Win32::Security::Authentication::Identity;
use super::errors::sec_status_to_io_error;
use super::handshake::SecCtx;
pub(crate) fn query_unique_bindings(ctx: &SecCtx) -> io::Result<Vec<u8>> {
let mut bindings: Identity::SecPkgContext_Bindings = unsafe { mem::zeroed() };
let status = unsafe {
Identity::QueryContextAttributesW(
ctx.raw(),
Identity::SECPKG_ATTR_UNIQUE_BINDINGS,
&mut bindings as *mut _ as *mut _,
)
};
if status != Foundation::SEC_E_OK {
return Err(sec_status_to_io_error(
status,
"QueryContextAttributesW(SECPKG_ATTR_UNIQUE_BINDINGS) failed",
));
}
let result = if bindings.Bindings.is_null() || bindings.BindingsLength == 0 {
Err(io::Error::other(
"QueryContextAttributesW(UNIQUE_BINDINGS) returned an empty buffer",
))
} else {
let token = unsafe {
std::slice::from_raw_parts(
bindings.Bindings as *const u8,
bindings.BindingsLength as usize,
)
.to_vec()
};
Ok(token)
};
if !bindings.Bindings.is_null() {
unsafe {
Identity::FreeContextBuffer(bindings.Bindings as *mut _);
}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn query_on_dummy_ctx_fails_to_extract() {
let dummy = SecCtx::for_test_only();
assert!(query_unique_bindings(&dummy).is_err());
}
}