OF-2694 & OF-2879: Add Channel binding support & implement XEP-0440#3282
OF-2694 & OF-2879: Add Channel binding support & implement XEP-0440#3282guusdk wants to merge 9 commits intoigniterealtime:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a pluggable channel-binding mechanism to Openfire, including a built-in tls-server-end-point implementation and initial wiring into Netty-based connections.
Changes:
- Introduces
ChannelBindingProvider+ChannelBindingProviderManagerto register and resolve channel binding data by RFC-defined prefix. - Implements
tls-server-end-pointchannel binding (RFC 5929) based on the server certificate hash, including RSASSA-PSS parameter parsing. - Exposes channel binding retrieval via
Connection#getChannelBindingData(...)and implements it inNettyConnection, with unit tests for both manager and provider.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| xmppserver/src/main/java/org/jivesoftware/util/channelbinding/ChannelBindingProvider.java | New SPI for channel binding extraction (per type/prefix). |
| xmppserver/src/main/java/org/jivesoftware/util/channelbinding/ChannelBindingProviderManager.java | New singleton manager for registering and querying providers. |
| xmppserver/src/main/java/org/jivesoftware/util/channelbinding/ChannelBindingType.java | New enum for well-known channel binding prefixes. |
| xmppserver/src/main/java/org/jivesoftware/util/channelbinding/TlsServerEndPointChannelBindingProvider.java | Implements RFC 5929 tls-server-end-point computation. |
| xmppserver/src/main/java/org/jivesoftware/openfire/Connection.java | Adds default getChannelBindingData(cbPrefix) API. |
| xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyConnection.java | Implements channel binding retrieval using the Netty SslHandler SSLEngine. |
| xmppserver/src/test/java/org/jivesoftware/util/channelbinding/ChannelBindingProviderManagerTest.java | Tests provider registration/ordering and lookup behavior. |
| xmppserver/src/test/java/org/jivesoftware/util/channelbinding/TlsServerEndPointChannelBindingProviderTest.java | Tests hashing behavior and algorithm resolution/normalization. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
95566f9 to
18c31e9
Compare
|
The first round of copilot's reviews were all pretty minor: unused import, input validation and white space changes, things like that. I've applied the changes to the original commit, and force-pushed those. |
|
I have now added support for exposing channel binding capable mechanisms through Openfire's SASL mechanism, and added one such mechanism: The new mechanism is advertised by default (unless configured otherwise, through preexisting options in the admin console). Additionally, I've added support for XEP-0440: SASL Channel-Binding Type Capability as tracked by OF-2879. I have tested the native support in Openfire of the
I'm unmarking this PR as draft. It is ready for review. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
a8d2268 to
79cce45
Compare
|
I have added a companion plugin to this work, here: https://github.com/igniterealtime/openfire-tlsexportercb-plugin This plugin uses the framework that is introduced in this PR. It adds the |
64891a7 to
ce2d1a5
Compare
|
This PR briefly had a commit that improves the reesilience of the SCARM-SHA-1 SASL implementation. I have now separated out those changes into distinct PRs: |
Fishbowler
left a comment
There was a problem hiding this comment.
This is ace! The comments are enough to put all the pieces together, even for a muggle like me.
A few comments, but all typographical in nature.
I've read every line, it all makes sense, but I've not run any tests on this yet.
ce2d1a5 to
f790903
Compare
|
I have addressed all suggestions from @Fishbowler (which were mostly spelling/text changes). I have also rebased this on Main now that #3288 was merged there. |
Add a channel binding abstraction consisting of: - ChannelBindingProvider interface for extracting channel binding data from an SSLEngine - ChannelBindingProviderManager to register, manage, and resolve providers per channel binding type - ChannelBindingType enum defining RFC-aligned binding identifiers - Comprehensive unit tests covering provider registration, ordering, resolution, and failure handling This introduces a best-effort mechanism to obtain channel binding data (as defined in RFC 5705, RFC 5929, and RFC 9266) without introducing hard dependencies on a specific TLS implementation or JDK version. The manager maintains an ordered list of providers per channel binding type and iterates through them until one successfully produces a value. Failures are isolated per provider, ensuring graceful degradation. Why this is needed Channel binding support is highly dependent on the capabilities of the underlying TLS stack and JDK version. Some mechanisms (notably newer exporter-based bindings) are difficult or effectively impossible to implement on older Java versions (e.g., Java 17), even when using reflection. At the same time, increasing the minimum required Java version for Openfire is undesirable, as it would negatively impact existing deployments. This change introduces a "manager/provider" pattern that: - Aligns with existing extensibility mechanisms used elsewhere in the codebase - Enables runtime discovery and prioritization of multiple implementations - Allows third parties to contribute additional providers via plugins Crucially, this design decouples channel binding support from the core runtime: - Core Openfire can remain compatible with Java 17 - Optional plugins can provide advanced implementations that depend on newer Java versions (e.g., Java 25+) These plugins can register their providers with the manager at runtime, seamlessly extending functionality without impacting baseline compatibility
…tion Introduce TlsServerEndPointChannelBindingProvider, an implementation of ChannelBindingProvider for the tls-server-end-point channel binding type as defined in RFC 5929. Implements logic to select the appropriate hash algorithm based on certificate signature algorithm, with special handling for RSASSA-PSS and weak hashes.
Expose per-connection channel binding data retrieval for SASL.
…ault This registers the corresponding provider without any ceremony. Future modifications could introduce configurability, but as support for this channel binding is mandatory per XEP, hard-coding seems acceptable.
Introduces SCRAM-SHA-1-PLUS SASL mechanism, implementing RFC 5802 channel binding for TLS. Advertise SCRAM-SHA-1-PLUS by default, but only when channel binding is available and session is encrypted.
With Channel Binding now available (as this commit follows commits that implements these under OF-2694), Openfire should announce what type of channel binding types it supports. The mechanism for this is define in XEP-0440. This commit implements this mechanism. Additionally, the channel binding type that is used for a session (if any) is now shown on its 'session details' page on the admin console.
…rage This adds more validation of the exchanged data in the SASL handshake, and adds more unit test coverage. Small refactorings have been applied to make ScramSha1SaslServer easier to unit-test. It now no longer unconditionally uses static calls to other classes. Such classes can be provided via a `@VisibleForTesting` constructor.
…when channel binding is supported Refactored SASL mechanism advertisement logic to ensure that -PLUS mechanisms (e.g., SCRAM-SHA-1-PLUS) are only offered when the current connection supports channel binding. The check now relies on Connection#getSupportedChannelBindingTypes(), which must return a non-empty set for -PLUS mechanisms to be advertised. Updated all relevant connection implementations (only NettyConnection, and the default method in the Connection interface) to ensure correct reporting of supported channel binding types. This change prevents authentication failures caused by advertising -PLUS mechanisms on connections that cannot provide channel binding data (e.g., WebSocket connections).
This addresses various typos and spelling issues. None of these are functionally changing anything.
f790903 to
b292378
Compare
|
I've rebased this to HEAD of Main, after merging changes for OF-3257 and OF-3258. |


Please refer to individual commit messages, but this adds an implementation for Channel Binding support, by:
tls-server-end-pointThis still lacks actual SASL support, and probably a couple of other things. I'm creating this PR as I'm looking for feedback (after churning way to much time on this).
After much experimentation, I've given up on
tls-exporteras a native thing in Openfire. The Java-native route requires Java 25 (where Openfire can go as low as 17), and BouncyCastle is giving me more nightmares.With this manager/provider mechanism, you can create a plugin that implements
tls-exporter. As plugins can define a minimum Java version of their own, that can be leveraged to gettls-exporterin deployments that run on Java 25. I've got a simple plugin in the works (not included here). I have tried implementingtls-exporterin Openfire directly, by using Java reflection to dynamically detect support for the API that was added in Java 25 (in an attempt to be able to include code that would be compatible yet not functional with Java 17), but I ran into problems with that approach. Notably, the added security layers with Java modules, made it all more messy than I am comfortable with.The
tls-server-end-pointimplementation was trickier than I thought, but at least we can do that in Openfire directly. I've refactored my earlier implementation to make use of that same provider mechanism, for consistency. That's included in this PR.