Skip to content

feat(sspi): server-side Kebreros implementation #440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Jun 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
dc63055
feat(kerberos): server-side kebreros;
TheBestTvarynka May 26, 2025
b5a67c5
feat(kerberos): server-side kebreros;
TheBestTvarynka May 27, 2025
96e7eea
feat(kerberos): server-side kebreros;
TheBestTvarynka May 28, 2025
1d2fa96
feat(sspi): make accept_security_context method async;
TheBestTvarynka May 28, 2025
001c329
refactor(sspi): tests and examples according to prev changes;
TheBestTvarynka May 28, 2025
e1ea9a0
feat(sspi): server-side kerberos;
TheBestTvarynka May 28, 2025
0d8258c
feat(sspi): implemented server-side kerberos for kerberos_kdc_auth te…
TheBestTvarynka May 29, 2025
192fc4b
feat(sspi): implemented server-side kerberos for kerberos_kdc_auth te…
TheBestTvarynka May 29, 2025
d011c10
feat(test): improve kerberos tests;
TheBestTvarynka May 29, 2025
8beed96
feat(test): improve integration tests;
TheBestTvarynka May 29, 2025
de5194d
feat(sspi): improve credssp integration tests. fix bugs in credssp se…
TheBestTvarynka Jun 2, 2025
7cb02fe
feat(sspi): kerberos: fix query_context_names method;
TheBestTvarynka Jun 2, 2025
bde9b7a
feat(sspi): kerberos: authenticators cache;
TheBestTvarynka Jun 2, 2025
a8b1e4b
refactor(sspi): credssp;
TheBestTvarynka Jun 3, 2025
2593b7a
refactor(sspi): small refactoring;
TheBestTvarynka Jun 3, 2025
d280516
refactor(sspi): small refactoring;
TheBestTvarynka Jun 3, 2025
9cc49a3
refactor(sspi): small refactoring;
TheBestTvarynka Jun 3, 2025
74bc374
refactor(sspi): small reactoring;
TheBestTvarynka Jun 4, 2025
c0427f6
refactor(sspi): small reactoring;
TheBestTvarynka Jun 4, 2025
cca194b
refactor(sspi): small reactoring;
TheBestTvarynka Jun 4, 2025
b4cb3a9
chore(sspi): update picky-* deps;
TheBestTvarynka Jun 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ picky = { version = "7.0.0-rc.12", default-features = false }
picky-asn1 = "0.10"
picky-asn1-der = "0.5"
picky-asn1-x509 = "0.14"
picky-krb = "0.9"
picky-krb = "0.10"
tokio = "1.44"
ffi-types = { path = "crates/ffi-types" }
winscard = { version = "0.2", path = "crates/winscard" }
Expand Down
8 changes: 4 additions & 4 deletions examples/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::net::{TcpListener, TcpStream};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use sspi::{
AuthIdentity, BufferType, CredentialUse, DataRepresentation, EncryptionFlags, Ntlm, SecurityBuffer,
SecurityBufferRef, SecurityStatus, ServerRequestFlags, Sspi, Username,
SecurityBufferRef, SecurityStatus, ServerRequestFlags, Sspi, SspiImpl, Username,
};

const IP: &str = "127.0.0.1:8080";
Expand Down Expand Up @@ -84,14 +84,14 @@ fn do_authentication(ntlm: &mut Ntlm, identity: &AuthIdentity, mut stream: &mut
loop {
read_message(&mut stream, &mut input_buffer[0].buffer)?;

let result = ntlm
let builder = ntlm
.accept_security_context()
.with_credentials_handle(&mut acq_cred_result.credentials_handle)
.with_context_requirements(ServerRequestFlags::ALLOCATE_MEMORY)
.with_target_data_representation(DataRepresentation::Native)
.with_input(&mut input_buffer)
.with_output(&mut output_buffer)
.execute(ntlm)?;
.with_output(&mut output_buffer);
let result = ntlm.accept_security_context_impl(builder)?.resolve_to_result()?;

if [SecurityStatus::CompleteAndContinue, SecurityStatus::CompleteNeeded].contains(&result.status) {
println!("Completing the token...");
Expand Down
11 changes: 6 additions & 5 deletions ffi/src/sspi/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use libc::{c_ulonglong, c_void};
use num_traits::cast::{FromPrimitive, ToPrimitive};
use sspi::{
BufferType, DataRepresentation, DecryptionFlags, EncryptionFlags, Error, ErrorKind, SecurityBuffer,
SecurityBufferRef, SecurityBufferType, ServerRequestFlags, Sspi,
SecurityBufferRef, SecurityBufferType, ServerRequestFlags, Sspi, SspiImpl,
};
#[cfg(windows)]
use symbol_rename_macro::rename_symbol;
Expand Down Expand Up @@ -100,13 +100,14 @@ pub unsafe extern "system" fn AcceptSecurityContext(

let mut output_tokens = vec![SecurityBuffer::new(Vec::with_capacity(1024), BufferType::Token)];

let result_status = sspi_context.accept_security_context()
.with_credentials_handle(&mut Some(auth_data))
let mut auth_data = Some(auth_data);
let builder = sspi_context.accept_security_context()
.with_credentials_handle(&mut auth_data)
.with_context_requirements(ServerRequestFlags::from_bits(f_context_req.try_into().unwrap()).unwrap())
.with_target_data_representation(DataRepresentation::from_u32(target_data_rep.try_into().unwrap()).unwrap())
.with_input(&mut input_tokens)
.with_output(&mut output_tokens)
.execute(sspi_context);
.with_output(&mut output_tokens);
let result_status = try_execute!(sspi_context.accept_security_context_impl(builder)).resolve_with_default_network_client();

// SAFETY: `p_output` is not null. We've checked this above.
try_execute!(unsafe { copy_to_c_sec_buffer((*p_output).p_buffers, &output_tokens, false) });
Expand Down
7 changes: 4 additions & 3 deletions ffi/src/sspi/sec_handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,10 @@ impl SspiImpl for SspiHandle {

fn accept_security_context_impl(
&mut self,
builder: sspi::builders::FilledAcceptSecurityContext<'_, Self::CredentialsHandle>,
) -> Result<sspi::AcceptSecurityContextResult> {
self.sspi_context.lock()?.accept_security_context_impl(builder)
builder: sspi::builders::FilledAcceptSecurityContext<Self::CredentialsHandle>,
) -> Result<sspi::generator::GeneratorAcceptSecurityContext> {
let mut context = self.sspi_context.lock()?;
Ok(context.accept_security_context_sync(builder).into())
}
}

Expand Down
21 changes: 3 additions & 18 deletions src/builders/accept_sec_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use super::{
ToAssign, WithContextRequirements, WithCredentialsHandle, WithOutput, WithTargetDataRepresentation,
WithoutContextRequirements, WithoutCredentialsHandle, WithoutOutput, WithoutTargetDataRepresentation,
};
use crate::generator::GeneratorAcceptSecurityContext;
use crate::{DataRepresentation, SecurityBuffer, SecurityStatus, ServerRequestFlags, ServerResponseFlags, SspiPackage};

pub type EmptyAcceptSecurityContext<'a, C> = AcceptSecurityContext<
Expand Down Expand Up @@ -252,24 +253,8 @@ impl<'a, CredsHandle> FilledAcceptSecurityContext<'a, CredsHandle> {
/// Executes the SSPI function that the builder represents.
pub fn execute<AuthData>(
self,
inner: SspiPackage<'_, CredsHandle, AuthData>,
) -> crate::Result<AcceptSecurityContextResult> {
inner: SspiPackage<'a, CredsHandle, AuthData>,
) -> crate::Result<GeneratorAcceptSecurityContext<'a>> {
inner.accept_security_context_impl(self)
}

pub(crate) fn transform(self) -> FilledAcceptSecurityContext<'a, CredsHandle> {
AcceptSecurityContext {
phantom_creds_use_set: PhantomData,
phantom_context_req_set: PhantomData,
phantom_data_repr_set: PhantomData,
phantom_output_set: PhantomData,

credentials_handle: self.credentials_handle,
context_requirements: self.context_requirements,
target_data_representation: self.target_data_representation,

output: self.output,
input: self.input,
}
}
}
Loading