Skip to content

Commit

Permalink
spnego: Reduce API surface
Browse files Browse the repository at this point in the history
  • Loading branch information
kiron1 committed Aug 18, 2024
1 parent 753a5ad commit c8102ea
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 24 deletions.
17 changes: 8 additions & 9 deletions spnego/src/gssapi.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
use libgssapi::{
context::{ClientCtx, CtxFlags},
name::Name,
oid::{Oid, GSS_NT_HOSTBASED_SERVICE},
oid::{GSS_MECH_SPNEGO, GSS_NT_HOSTBASED_SERVICE},
};
use std::result::Result;

// GSS_SPNEGO_MECHANISM - 1.3.6.1.5.5.2
static GSS_MECH_SPNEGO: Oid = Oid::from_slice(b"\x2b\x06\x01\x05\x05\x02");

#[derive(Debug)]
pub struct Context {
pub(super) struct Context {
cx: ClientCtx,
}

impl Context {
pub fn new(service: &str, proxy_fqdn: &str) -> Result<Self, libgssapi::error::Error> {
pub(super) fn new(
service: &str,
proxy_fqdn: &str,
) -> std::result::Result<Self, libgssapi::error::Error> {
// GSS-API uses service@host format, while
// Kerberos SPN uses service/host@REALM (@REALM is optional).
let target = format!("{service}@{proxy_fqdn}");
Expand All @@ -34,10 +33,10 @@ impl Context {
}

// Call `step` `while request.status() == http::StatusCode::PROXY_AUTHENTICATION_REQUIRED {}`.
pub fn step(
pub(super) fn step(
&mut self,
server_token: Option<&[u8]>,
) -> Result<Option<Vec<u8>>, libgssapi::error::Error> {
) -> std::result::Result<Option<Vec<u8>>, libgssapi::error::Error> {
let token = self.cx.step(server_token, None);
match token {
Ok(Some(token)) => Ok(Some(Vec::from(&*token))),
Expand Down
64 changes: 58 additions & 6 deletions spnego/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,63 @@
#[cfg(unix)]
pub mod gssapi;
mod gssapi;

#[cfg(windows)]
pub mod sspi;
mod sspi;

#[cfg(unix)]
pub use gssapi::Context;
#[derive(Debug)]
pub struct Context {
#[cfg(unix)]
inner: gssapi::Context,

#[cfg(windows)]
pub use sspi::Context;
#[cfg(windows)]
inner: sspi::Context,
}

impl Context {
pub fn new(service: &str, proxy_fqdn: &str) -> crate::Result<Self> {
#[cfg(unix)]
{
Ok(Self {
inner: gssapi::Context::new(service, proxy_fqdn)
.map_err(|inner| Error { inner })?,
})
}

#[cfg(windows)]
{
Ok(Self {
inner: sspi::Context::new(service, proxy_fqdn).map_err(|inner| Error { inner })?,
})
}
}

pub fn step(&mut self, server_token: Option<&[u8]>) -> crate::Result<Option<Vec<u8>>> {
self.inner
.step(server_token)
.map_err(|inner| Error { inner })
}
}

#[derive(Debug)]
pub struct Error {
#[cfg(unix)]
inner: libgssapi::error::Error,

#[cfg(windows)]
inner: windows::core::Error,
}

pub type Result<T> = std::result::Result<T, Error>;

impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.inner)
}
}

impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("SPNEGO error: ")?;
self.inner.fmt(f)
}
}
20 changes: 11 additions & 9 deletions spnego/src/sspi.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::ffi::c_void;

pub use windows::core::{Error, HRESULT, PCWSTR};
pub use windows::Win32::Security::{
use windows::core::PCWSTR;
use windows::Win32::Security::{
Authentication::Identity::{
AcquireCredentialsHandleW, InitializeSecurityContextW, SecBuffer, SecBufferDesc,
ISC_REQ_MUTUAL_AUTH, SECBUFFER_TOKEN, SECBUFFER_VERSION, SECPKG_CRED_OUTBOUND,
Expand All @@ -15,7 +15,7 @@ type TimeStamp = i64;
// https://github.com/java-native-access/jna/issues/261
const MAX_TOKEN_SIZE: usize = 48 * 1024;

pub struct Context {
pub(super) struct Context {
cx: SecHandle,
cred: SecHandle,
target: String,
Expand All @@ -42,7 +42,10 @@ fn to_utf16(value: &str) -> Vec<u16> {
}

impl Context {
pub fn new(service: &str, proxy_fqdn: &str) -> Result<Self, Error> {
pub(super) fn new(
service: &str,
proxy_fqdn: &str,
) -> std::result::Result<Self, windows::core::Error> {
let target = format!("{service}/{proxy_fqdn}");
let spn = to_utf16(&target);

Expand Down Expand Up @@ -76,14 +79,13 @@ impl Context {
})
}

pub fn target_name(&self) -> &str {
&self.target
}

// TODO: server token is not used right now.
// https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-grvhenc/b9e676e7-e787-4020-9840-7cfe7c76044a?redirectedfrom=MSDN
// https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc772815(v=ws.10)
pub fn step(&mut self, _server_token: Option<&[u8]>) -> Result<Option<Vec<u8>>, Error> {
pub(super) fn step(
&mut self,
_server_token: Option<&[u8]>,
) -> std::result::Result<Option<Vec<u8>>, windows::core::Error> {
let mut buf = Vec::with_capacity(MAX_TOKEN_SIZE);
buf.resize(MAX_TOKEN_SIZE, 0);
let mut sec_buffer = [SecBuffer {
Expand Down

0 comments on commit c8102ea

Please sign in to comment.