Skip to content

feat(kerberos): add support for IAKerb extension for Kerberos client - #751

Open
Rostyslav-Romanets wants to merge 5 commits into
Devolutions:masterfrom
Rostyslav-Romanets:ia-kerb-support
Open

Rostyslav-Romanets wants to merge 5 commits into
Devolutions:masterfrom
Rostyslav-Romanets:ia-kerb-support

Conversation

@Rostyslav-Romanets

@Rostyslav-Romanets Rostyslav-Romanets commented Sep 24, 2026 •

Copy link
Copy Markdown

This PR adds support for the IAKERB extension according to the IAKERB specification.

The main changes are focused on the Kerberos state machine. Previously, the Preauthentication state handled the entire KDC message exchange withing a single async intialize_security_context call. This approach does not work with IAKERB, where KDC messages are exchanged via a server that acts as a proxy. The Preauthentication state has therefore been split into multiple states, allowing the state machine to save Kerberos state between KDC message exchanges.

Additionaly, the AS and TGS exchanges have been extracted into separate state machines. These new state machines are KDC transport-agnostic and can be used with both external KDC and an IAKERB proxy.

What is IAKERB

IAKERB extends Kerberos to support scenarios where the client cannot directly access the KDC. Instead, KDC messages are encapsulated in GSS-API tokens and exchanged through an IAKERB proxy. The server forwards these messages to the LocalKDC, allowing the client to obtain the required Kerberos tickets without direct network access to the KDC.

Microsoft recently introduced IAKERB support in Windows Insider builds as part of its effort to reduce NTLM dependency: https://techcommunity.microsoft.com/blog/windows-itpro-blog/reducing-ntlm-dependency-iakerb-and-localkdc-in-windows-insider-preview/4524615.

Related PRs

Comment thread Cargo.toml
proptest = "1.6"
cfg-if = "1"

[patch.crates-io]

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These patches of picky-rs can be removed once a new version containing the following changes will be released: (Devolutions/picky-rs#531) will be released.

Comment thread src/negotiate/client.rs
}

let neg_result = if !negotiate.mic_needed || negotiate.mic_verified {
// TODO(FIX): The client rejects the server's `mechListMIC`: https://github.com/Devolutions/sspi-rs/issues/748

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disabled the MIC token verification due to this issue: #748

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Dependency resolution, workspace compilation, cross-realm transitions, state preservation, mechanism framing, and SPNEGO MIC verification contain blocking issues.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 4 High severity · 2 Medium severity

Open (6)
What changed in this PR

Adds IAKERB proxy support to Kerberos authentication and restructures AS/TGS exchanges into resumable state machines.

Changes:

  • Adds IAKERB configuration, framing, cookies, transcript checksums, and SPNEGO negotiation.
  • Splits Kerberos client/server exchange states and secures DH private keys.
  • Updates callers, tests, FFI, and picky dependencies.
File Description
tests/​sspi/​client_server/​kerberos/​mod.rs Updates Kerberos configurations and exchange counts.
tests/​sspi/​client_server/​credssp.rs Updates configuration and CredSSP step count.
src/​utils.rs Maps IAKERB proxy errors.
src/​pku2u/​server.rs Wraps DH private keys as secrets.
src/​pku2u/​mod.rs Reads secret DH keys.
src/​pku2u/​generators.rs Generates secret DH keys.
src/​pk_init.rs Secures DH parameters.
src/​negotiate/​server.rs Adjusts final MIC handling.
src/​negotiate/​mod.rs Adds IAKERB mechanism selection.
src/​negotiate/​generators.rs Advertises the IAKERB mechanism.
src/​negotiate/​client.rs Integrates IAKERB and MIC exchange behavior.
src/​lib.rs Exports KDC resolution configuration.
src/​kerberos/​tests.rs Updates test contexts for new state fields.
src/​kerberos/​server/​mod.rs Introduces server-specific states.
src/​kerberos/​server/​as_exchange.rs Hosts transport-based AS exchange logic.
src/​kerberos/​pa_datas.rs Reads protected DH keys.
src/​kerberos/​mod.rs Adds split states and IAKERB context data.
src/​kerberos/​messages.rs Encodes IAKERB proxy messages.
src/​kerberos/​config.rs Adds KDC resolution strategies.
src/​kerberos/​client/​mod.rs Implements resumable Kerberos client exchanges.
src/​kerberos/​client/​kdc/​tgs_exchange.rs Adds the TGS exchange state machine.
src/​kerberos/​client/​kdc/​mod.rs Decodes direct and proxied KDC replies.
src/​kerberos/​client/​kdc/​as_exchange.rs Adds the AS exchange state machine.
src/​kerberos/​client/​generators.rs Serializes authenticator extensions.
src/​kerberos/​client/​extractors.rs Validates preauthentication errors.
src/​kerberos/​client/​change_password.rs Rejects IAKERB password changes.
src/​kerberos/​client/​as_exchange.rs Removes the previous AS exchange implementation.
src/​auth_identity.rs Adds protected password extraction.
ffi/​src/​sspi/​sec_handle.rs Migrates FFI configuration construction.
examples/​kerberos.rs Updates the Kerberos example constructor.
Cargo.toml Adds local picky dependency patches.
Cargo.lock Records locally patched picky packages.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Cargo.toml Outdated
Comment thread src/kerberos/client/kdc/tgs_exchange.rs
Comment thread src/kerberos/config.rs
Comment on lines +33 to +35
pub struct KerberosConfig {
/// Strategy for resolving the KDC to use for Kerberos authentication.
pub kdc_resolution: KdcResolution,

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment thread src/negotiate/client.rs
Comment on lines +244 to +248
// TODO(FIX): The client rejects the server's `mechListMIC`: https://github.com/Devolutions/sspi-rs/issues/748
// if negotiate.mic_needed {
// negotiate.verify_mic_token(mech_list_mic.as_deref())?;
// }
negotiate.mic_verified = true;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MIC token verification has an issue which is not fixed yet: #752.
The verification is commented for now, since the authentication fails.

Comment thread src/kerberos/client/mod.rs Outdated
Comment thread src/kerberos/client/mod.rs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes for the three blocking issues already documented in open inline threads (avoiding duplicate comments): the sibling-only picky dependency patches prevent a clean checkout from building (#751 (comment)); cross-realm referrals never transition back to TgsRequest (#751 (comment)); and the client accepts the server mechListMIC without verification for every SPNEGO mechanism (#751 (comment)). I reproduced the dependency failure with cargo check --locked --offline -p sspi. Please resolve these before merging.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The IAKERB Finished checksum currently uses the wrong key usage and byte order, preventing interoperable authentication.

Review effort: Balanced
Findings: 5 High severity

Open (5)
Resolved since last review (4)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Map IAKERB availability failures to NoAuthenticatingAuthority

src/​utils.rs:217

Both errors mean the proxy could not reach a KDC, but mapping them to KdcInvalidRequest prevents Negotiate's documented NTLM fallback, which only handles such network/proxy failures as NoAuthenticatingAuthority (src/negotiate/client.rs:17-30). Map both IAKERB availability errors accordingly so authentication can fall back when NTLM is enabled.

Comment thread src/kerberos/client/generators.rs
Comment on lines +563 to +567
vec![generate_authenticator_extension(
&authenticator_sub_key,
&client.iakerb_gss_transcript,
&enc_type.cipher().checksum_type(),
)?]

@Rostyslav-Romanets Rostyslav-Romanets Sep 29, 2026 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The KEY_USAGE_IAKERB_FINISHED should be used for interoperability with previous MIT versions: https://datatracker.ietf.org/doc/html/draft-ietf-kitten-iakerb-03#appendix-A
The real Windows implementation returns CredSSP error if KEY_USAGE_IAKERB_FINISHED is used.

Comment thread src/pku2u/server.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Direct IAKERB contexts can incorrectly initiate U2U, proxy availability errors prevent fallback, and the new exchange lacks end-to-end coverage.

Review effort: Balanced
Findings: 4 High severity

Open (4)
Resolved since last review (2)
Previously missed (4)

In code that hasn't changed since last review

Medium severity Classify proxy availability failures as NoAuthenticatingAuthority

src/​utils.rs:217

Both proxy availability failures are classified as KdcInvalidRequest, so Negotiate will not take its documented network/proxy-error fallback path, which only recognizes NoAuthenticatingAuthority (src/negotiate/client.rs:17-30). These codes mean the proxy could not locate or contact a KDC, not that the client request was invalid; classify them as NoAuthenticatingAuthority so callers receive the correct SSPI status and configured NTLM fallback remains functional.

Low severity Add end-to-end multi-call IAKERB state-machine coverage

src/​kerberos/​client/​mod.rs:276

The new multi-call IAKERB branch has no end-to-end state-machine test; the added test only exercises decode_kdc_reply. Add a mocked AS-error/AS-reply/TGS-reply exchange that checks each ContinueNeeded proxy token, cookie forwarding, transcript accumulation, and the final AP request so regressions in the core feature are detected.

Low severity Report the actual invalid server state in diagnostics

src/​kerberos/​client/​mod.rs:697

Because mem::take has already installed the default Failed state, this error always says the context was in Failed rather than identifying the actual Final or Server state that caused the out-of-sequence call. Bind and report the consumed state instead.

Low severity Report the actual invalid client state in diagnostics

src/​kerberos/​server/​mod.rs:171

mem::take has already replaced server.state with Failed, so this diagnostic always reports Failed instead of the actual invalid Client or Final state. Bind the matched value and format it directly to preserve an actionable out-of-sequence error.

Comment on lines +107 to +108
loop {
let status = match core::mem::take(&mut client.state) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@CBenoit

Copy link
Copy Markdown
Member

Hi Rostyslav-Romanets

The new picky crates are now published 🙂

@CBenoit

Copy link
Copy Markdown
Member

Copilot also still have a few "High" findings, did you confirm whether it was false positives or fixed?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants