Please review a fix that makes the SSPI bridge pass channel bindings to 
`InitializeSecurityContext`.

`gss_init_sec_context` in `sspi.cpp` receives `input_chan_bindings`, but never 
passes a `SECBUFFER_CHANNEL_BINDINGS` buffer to `InitializeSecurityContext`. A 
server that requires channel binding (for example IIS with Extended Protection 
"Always") rejects the Kerberos token, and the client gets 401.

The patch adds `convert_chan_bindings`. It builds a `SEC_CHANNEL_BINDINGS` blob 
from `input_chan_bindings` and passes it as an extra input buffer on every 
call, unless the caller passes `GSS_C_NO_CHANNEL_BINDINGS`.

The patch proposed in the bug report fails with `SEC_E_UNSUPPORTED_FUNCTION` 
when either address is non-empty. This patch copies the initiator and acceptor 
address types and bytes into the structure instead, for two reasons:

- The built-in TLS binding (`TlsChannelBindingImpl`) has no addresses (type 0, 
empty). But `org.ietf.jgss.ChannelBinding(InetAddress, InetAddress, byte[])` is 
public API, so applications can set addresses. The pure-Java Kerberos initiator 
supports that, and rejecting it would make the native bridge behave differently.
- The Kerberos checksum carries an MD5 over the address types, lengths, address 
bytes and application data (RFC 4121 section 4.1.1.2). The acceptor hashes 
whatever it was given, so dropping the addresses would make the hashes differ.

The address type is copied even when the address is empty, because it is part 
of the hash. TLS uses 0 and other bindings use `GSS_C_AF_NULLADDR` (255). These 
are set by `newGSSCB`.

**Testing.**
Verified on a non-domain-joined Windows 11 machine. An MIT KDC (realm 
TEST.LOCAL) runs in WSL. A Java HTTPS server (Java GSS, SPN 
`HTTP/host.test.local`) enforces channel binding with the 
`tls-server-end-point` hash of its certificate, to mimic IIS Extended 
Protection "Always". The client is `HttpsURLConnection`, started with `runas 
/netonly`, `-Dsun.security.jgss.native=true` and 
`-Djdk.https.negotiate.cbt=always`. 

The client runs in three modes:
(A) baseline, 
(B) A plus `-Djavax.security.auth.useSubjectCredsOnly=false`, 
(C) B with no Authenticator and a browser-style User-Agent, as in the bug 
report.

- Without the fix, all three failed with `GSSException: Channel binding 
mismatch (Mechanism level: Token missing ChannelBinding!)`.
- With the fix, all three passed (`Auth SUCCESS - client: [email protected]`).

---------
- [X] I confirm that I make this contribution in accordance with the [OpenJDK 
Interim AI Policy](https://openjdk.org/legal/ai).

-------------

Commit messages:
 - 8387963: sspi.cpp drops Kerberos Channel Binding

Changes: https://git.openjdk.org/jdk/pull/33528/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=33528&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8387963
  Stats: 98 lines in 1 file changed: 89 ins; 3 del; 6 mod
  Patch: https://git.openjdk.org/jdk/pull/33528.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/33528/head:pull/33528

PR: https://git.openjdk.org/jdk/pull/33528

Reply via email to