Skip to content

Tags: Devolutions/sspi-rs

Tags

sspi-v0.21.3

Toggle sspi-v0.21.3's commit message
chore: Release package sspi version 0.21.3

v2026.07.15.0

Toggle v2026.07.15.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(dns): avoid panic on short SRV record RDATA on macOS (#706)

We've received crash reports from a client application on macOS showing

> thread " (46265) panicked at src/dns.rs:172:56: range end index 2 out
of range for slice of length O
note: run with 'RUST_BACKTRACE=1' environment variable to display a
backtrace

It's the first we've seen of it, but this client reports that it crashes
_consistently_ in his environment.

The cited line lands exactly on `rdata[0..2]` inside the SRV-record
parser. Presumably the `rdata` buffer was empty so slicing it caused a
panic. But why is the record empty? I'm not sure.

Every callback from the DNS query returns a `DnsSrvRecord `, where the
RDATA is at least 6 bytes (priority + weight + port, then the target
name). The code assumes a well formed SRV record. We see some
(potential) defects in the code:

1. The parser is unguarded and trusts `rdata` to always be at least 6
bytes
2. I believe (but am not sure) that the normal "this realm has no SRV
record" outcome is **not** an empty callback, but a timeout.
mDNSResponder doesn't call back in time, our timeout fires and we return
an empty list. I guess in this case _something_ causes the SRV query to
be answered immediately, with a negative (empty) response. I'm equally
not sure what that could be: VPN resolver, enterprise DNS, a local stub
resolver.... Not sure.

The (blind) fix:

In `src/dns.rs`, in the macOS/iOS path:

- From → TryFrom, returning `Err` when `rdata.len() < 6` instead of
slicing
- The query loop now filters on the `ADD` flag (the correct signal for
"this is a real, added record"), skipping negative responses and
removals rather than parsing them.
- Both skip cases are logged (`debug!`/`warn!`) with the record's
`rr_type`, `rr_class`, and `rdata_len`, so if a resolver sends something
unexpected again, we can see exactly what it returned instead of
guessing.

For a realm with no SRV records, the empty/negative answer is ignored,
we now fall through to the UDP query and then return an empty host list.

sspi-v0.21.2

Toggle sspi-v0.21.2's commit message
chore: Release package sspi version 0.21.2

winscard-v0.3.3

Toggle winscard-v0.3.3's commit message
chore: Release package winscard version 0.3.3

sspi-v0.21.1

Toggle sspi-v0.21.1's commit message
chore: Release package sspi version 0.21.1

v2026.06.24.0

Toggle v2026.06.24.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: support for Kerberos cross realm referral (#694)

RDP/NLA via FreeRDP and sspi-rs failed when a parent-domain user
(richard@rjm.local) authenticated to a host in a child domain
(TERMSRV/WIN-UE7FOENEK0D.dev.rjm.local) with

> InvalidToken: Asn1 error: "Expected Application number tag 15 but got:
30"

(Kerberos app tags: 15 = `AP-REP`, 30 = `KRB-ERROR` — i.e. we expected
an `AP-REP` from the server but got a `KRB-ERROR`.)

### Root cause

sspi-rs has no cross-realm referral chasing. A KDC only issues tickets
for principals in its own realm; for a service in another realm it
returns a referral `TGT` (sname = krbtgt/<NEXT_REALM>), and the client
must re-send the `TGS-REQ` to that next realm. Instead, sspi-rs:

1. Sent the `TGS-REQ` to the home KDC (RJM.LOCAL) → got back a referral
`TGT` for krbtgt/DEV.RJM.LOCAL.
2. Stuffed that referral `TGT` directly into the `AP_REQ` as if it were
the service ticket.
3. The target (WIN-UE7FOENEK0D) couldn't decrypt a ticket encrypted with
the trust key; returned `KRB-ERROR` 41 (`KRB_AP_ERR_MODIFIED`).
4. sspi-rs tried to parse that `KRB-ERROR` as an `AP-REP` --->
`InvalidToken`.

### What we changed

Referral chasing loop in the `TGS` exchange
(src/kerberos/client/mod.rs): after each `TGS-REP`, if the returned
ticket sname is krbtgt/<NEXT_REALM>, re-issue the `TGS-REQ` for the same
SPN to that realm using the referral `TGT`, chaining the session key and
authenticator each hop, until the real service ticket comes back.
Bounded to 10 hops with a no-progress guard.

Per-realm KDC routing (src/kerberos/mod.rs): split send into
`send`/`send_to` and added `send_for_realm`. The pinned kdc_url (KDC
proxy) stays authoritative for the home realm only; referral hops
resolve through `detect_kdc_url(realm)`.

Helper and tests: extracted` referral_target_realm(sname)` (testable
predicate) with 5 unit tests.

### Key decisions

Reuse the existing per-realm resolution chain rather than add new
config. Referral hops route via the existing `SSPI_KDC_URL_<REALM>` env
→ krb5.conf → DNS SRV (_kerberos._tcp.<realm>) fallback. No new
FFI/config plumbing; set one env var (or rely on DNS) and it works.

Pinned KDC = home realm only. A KDC proxy pinned to the home DC can't
decrypt a krbtgt/<NEXT_REALM> referral ticket, so referral hops must
reach the target realm's KDC.

### For further discussion

(Because I'm trying to keep these changes focussed)

Windows DNS SRV limitations
([src/dns.rs](vscode-webview://0o7221v7omgideiac71911ugm38hnasf8rt28rpk2ejj6sje9p7m/src/dns.rs)):
the Windows path forces port :88 (ignores the SRV port) and reads only
the first SRV record (no multi-DC failover).

Dotted env-var friction: SSPI_KDC_URL_DEV.RJM.LOCAL breaks PowerShell
$env: parsing. Add underscore-normalized aliasing
(SSPI_KDC_URL_DEV_RJM_LOCAL)?

U2U + referral interaction: `additional_tickets` is only carried on the
first hop; edge case, likely fine, but worth a sanity check.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

v2026.06.01.0

Toggle v2026.06.01.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(ffi): Don't attempt to package tests during NuGet CI build (#683)

PR #679 added some smoke tests, but this breaks the CI script which
tries to build and package the whole solution, including the tests.

v2026.05.06.0

Toggle v2026.05.06.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix!: remove redundant PKCS#1 padding when signing hashes (#660)

sspi-v0.21.0

Toggle sspi-v0.21.0's commit message
chore: Release package sspi version 0.21.0

winscard-v0.3.2

Toggle winscard-v0.3.2's commit message
chore: Release package winscard version 0.3.2