Skip to content

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

Merged
Marc-André Moreau (mamoreau-devolutions) merged 1 commit into
Devolutions:masterfrom
Rostyslav-Romanets:ia-kerb-support
Oct 19, 2026
Merged

Marc-André Moreau (mamoreau-devolutions) merged 1 commit into
Devolutions:masterfrom
Rostyslav-Romanets:ia-kerb-support

Conversation

@Rostyslav-Romanets

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

Copy link
Copy Markdown
Contributor

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 Outdated
proptest = "1.6"
cfg-if = "1"

[patch.crates-io]

Copy link
Copy Markdown
Contributor 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 Outdated
}

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
Contributor 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 Resolved
Comment thread src/kerberos/client/kdc/tgs_exchange.rs Resolved
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
Contributor 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 Resolved
Comment thread src/kerberos/client/mod.rs Resolved
Comment thread src/kerberos/client/mod.rs Resolved

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 Resolved
Comment thread src/kerberos/client/mod.rs Resolved
Comment thread src/pku2u/server.rs Resolved

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 thread src/kerberos/client/mod.rs Resolved
@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?

@Rostyslav-Romanets

Copy link
Copy Markdown
Contributor Author

Benoît Cortier (@CBenoit)

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

I have fixed all issues found by Copilot. Some findings are false positive, I explained why in comments.
Also I have rebased this branch on the latest master branch.

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

Remaining configuration compile errors, lost TGS clock correction, and an incomplete SPNEGO state transition must be fixed.

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

Open (5)
Resolved since last review (2)

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
Contributor 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/kerberos/client/kdc/tgs_exchange.rs Resolved
Comment thread src/negotiate/server.rs Resolved

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

IAKERB KDC failures bypass established NTLM fallback, and the primary multi-step IAKERB flow lacks authentication coverage.

Review effort: Balanced
Findings: 3 High severity · 1 Low severity

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

In code that hasn't changed since last review

Medium severity Map KdcInvalidRequest to NTLM fallback errors

src/​utils.rs:217

These two errors describe KDC unavailability, but KdcInvalidRequest is not in NTLM_FALLBACK_ERROR_KINDS. As a result, Negotiate configured for IAKERB aborts instead of following the existing fallback behavior for an unreachable/missing KDC (src/negotiate/client.rs:17-30). Map them to NoAuthenticatingAuthority, as direct KDC discovery/transport failures already do.

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

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.

🔵 Needs a closer look

The authentication state-machine and protocol changes are security-sensitive and warrant final human interoperability review.

5 open findings
1 resolved since last review

🧠 Review effort: Balanced

Comment thread src/kerberos/client/change_password.rs Resolved
Comment thread src/negotiate/generators.rs Resolved
Comment thread src/utils.rs Resolved

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.

Comment thread src/kerberos/client/kdc/tgs_exchange.rs Resolved
Comment thread src/kerberos/server/mod.rs Resolved

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.

🟡 Changes recommended

SPNEGO currently accepts an unadvertised IAKERB mechanism, allowing the server to change the configured KDC transport mode.

4 open findings
4 resolved since last review
Previously missed (2)

In code that hasn't changed since last review

Low severity Remove trailing punctuation from warning

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

This new warning violates the repository log-message convention by ending with punctuation. Remove the trailing ellipsis.

Low severity Add SPNEGO integration coverage for IAKERB

src/​negotiate/​generators.rs:35

The new IAKERB SPNEGO path is not covered by the added integration test, which drives Kerberos directly. Add a Negotiate-level test that verifies the IAKERB OID advertisement, proxy round trips, selected-mechanism handling, and final MIC exchange; the existing SPNEGO suite in tests/sspi/client_server/kerberos/mod.rs shows this layer is otherwise comprehensively tested.

🧠 Review effort: Balanced

Comment thread src/negotiate/mod.rs Resolved

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.

Comment thread src/negotiate/client.rs Resolved
Comment thread src/negotiate/extractors.rs Resolved

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.

🟡 Changes recommended

The new SPNEGO IAKERB test passes an unsupported mechanism to the built-in acceptor and cannot complete authentication.

3 open findings
2 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Medium severity Assert against the variables actually passed to the decoder

src/​kerberos/​client/​kdc/​mod.rs:205

The decoder receives temporary clones, but the assertions below inspect the untouched originals. These assertions therefore pass even if the external-KDC path incorrectly mutates the cookie or transcript. Make the original variables mutable and pass them directly.

🧠 Review effort: Balanced

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.

🔵 Needs a closer look

Security-sensitive authentication state changes and Windows-specific interoperability behavior require final human validation.

2 open findings
1 resolved since last review

🧠 Review effort: Balanced

@Rostyslav-Romanets

Rostyslav-Romanets commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor Author

Benoît Cortier (@CBenoit) Marc-André Moreau (@mamoreau-devolutions) Hi, I have fixed all the remaining issues found by Copilot. Can you take a look? The two open findings from Copilot have been fixed, but it didn't close them.

Also, this PR should be merged after #772, which fixes the issue with mechListMIC for Kerberos client.

@mamoreau-devolutions

Copy link
Copy Markdown
Contributor

Rostyslav-Romanets #772 has been merged

@Rostyslav-Romanets

Copy link
Copy Markdown
Contributor Author

Rostyslav-Romanets #772 has been merged

Marc-André Moreau (@mamoreau-devolutions) Thanks! I have also rebased this PR on the latest master, and it is ready for merge too.

@mamoreau-devolutions
Marc-André Moreau (mamoreau-devolutions) merged commit a738671 into Devolutions:master Oct 19, 2026
68 checks passed
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