Skip to content

Fix S2S dialback not offered in post-TLS features when self-signed certs accepted#3291

Open
milne1282 wants to merge 4 commits into
igniterealtime:mainfrom
milne1282:fix/s2s-selfsigned-dialback-property
Open

Fix S2S dialback not offered in post-TLS features when self-signed certs accepted#3291
milne1282 wants to merge 4 commits into
igniterealtime:mainfrom
milne1282:fix/s2s-selfsigned-dialback-property

Conversation

@milne1282
Copy link
Copy Markdown

@milne1282 milne1282 commented Apr 24, 2026

ServerDialback.isEnabledForSelfSigned() reads the legacy property xmpp.server.certificate.accept-selfsigned (TLS_ACCEPT_SELFSIGNED_CERTS), but ConnectionListener.setAcceptSelfSignedCertificates() — which backs the Admin Console UI checkbox — writes to the per-connection-type prefixed property xmpp.socket.ssl.certificate.accept-selfsigned. These diverged when per-type prefixed properties were introduced but the readers in ServerDialback were not updated.

The consequence is that after a successful TLS handshake with a self-signed peer certificate, LocalIncomingServerSession.getAvailableStreamFeatures() calls isEnabledForSelfSigned(), gets false, and omits db:dialback from the post-TLS stream:features. The connecting server then finds no usable authentication mechanism and closes the connection. This causes all encrypted S2S connections to fail silently when the only option is dialback, even if the operator has enabled self-signed certificate acceptance via the UI.

Fix: check both property names in isEnabledForSelfSigned(), preserving full backwards compatibility with installations that have the legacy property set.

@guusdk
Copy link
Copy Markdown
Member

guusdk commented Apr 25, 2026

Oh, interesting. Thanks for this @milne1282 ! Did you happen to check if other connection types suffer from a similar issue, triggered by the same type of divergence after the prefixed properties were introduced?

@milne1282
Copy link
Copy Markdown
Author

milne1282 commented Apr 25, 2026

Hey @guusdk I have not checked other properties as I was focused on an implementation topology that this affected and have not made a more general search

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 87526a90-e8d8-4679-a3d4-f1d9f28df424

📥 Commits

Reviewing files that changed from the base of the PR and between 0bbf1e2 and d750017.

📒 Files selected for processing (7)
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/ClientTrustManager.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/ServerStanzaHandler.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/ServerTrustManager.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/TLSStreamHandler.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/server/ServerDialback.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/session/ConnectionSettings.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionListener.java
✅ Files skipped from review due to trivial changes (1)
  • xmppserver/src/main/java/org/jivesoftware/openfire/session/ConnectionSettings.java
🚧 Files skipped from review as they are similar to previous changes (5)
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/TLSStreamHandler.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/ServerTrustManager.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/ServerStanzaHandler.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/ClientTrustManager.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionListener.java

📝 Walkthrough

Walkthrough

This PR migrates TLS certificate validation from a global property-based system to a connection-listener-based approach, deprecating legacy configurations in ClientTrustManager, ServerTrustManager, and related certificate handling classes while introducing recursive property fallback logic in ConnectionListener.

Changes

TLS Configuration Migration to Connection-Listener Model

Layer / File(s) Summary
Deprecation Markers & Configuration
xmppserver/src/main/java/org/jivesoftware/openfire/session/ConnectionSettings.java
Five server TLS certificate verification constants (TLS_ACCEPT_SELFSIGNED_CERTS, TLS_CERTIFICATE_VERIFY, TLS_CERTIFICATE_VERIFY_VALIDITY, TLS_CERTIFICATE_ROOT_VERIFY, TLS_CERTIFICATE_CHAIN_VERIFY) are marked @Deprecated(forRemoval = true, since = "5.1.0").
New Property Resolution Mechanism
xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionListener.java
acceptSelfSignedCertificates() and verifyCertificateValidity() are refactored to perform recursive, multi-hop property resolution across connection type fallbacks, consulting both deprecated and new configuration sources.
Trust Manager Deprecation & Integration
xmppserver/src/main/java/org/jivesoftware/openfire/net/ClientTrustManager.java, xmppserver/src/main/java/org/jivesoftware/openfire/net/ServerTrustManager.java
ClientTrustManager and ServerTrustManager are marked @Deprecated(forRemoval = true, since = "5.1.0"); both now retrieve ConnectionListener and delegate certificate validation to listener.verifyCertificateValidity() and listener.acceptSelfSignedCertificates() instead of using global properties.
TLS Handler Integration
xmppserver/src/main/java/org/jivesoftware/openfire/net/ServerStanzaHandler.java, xmppserver/src/main/java/org/jivesoftware/openfire/net/TLSStreamHandler.java, xmppserver/src/main/java/org/jivesoftware/openfire/server/ServerDialback.java
ServerStanzaHandler and TLSStreamHandler replace global TLS_ACCEPT_SELFSIGNED_CERTS checks with listener-based configuration; ServerDialback.isEnabledForSelfSigned() delegates to the S2S listener, and setEnabledForSelfSigned() is marked deprecated.
License Updates
xmppserver/src/main/java/org/jivesoftware/openfire/net/ClientTrustManager.java, xmppserver/src/main/java/org/jivesoftware/openfire/net/ServerStanzaHandler.java, xmppserver/src/main/java/org/jivesoftware/openfire/net/ServerTrustManager.java, xmppserver/src/main/java/org/jivesoftware/openfire/net/TLSStreamHandler.java
Copyright header years are updated to 2017-2026.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • igniterealtime/Openfire#3308: Related — both change ConnectionListener's self-signed certificate acceptance logic: the main PR refactors acceptSelfSignedCertificates/verifyCertificateValidity, and the retrieved PR fixes the wrong getter used in setAcceptSelfSignedCertificates.

Suggested reviewers

  • akrherz

Poem

🐰 From global props to listeners so keen,
Trust managers shed their role supreme,
Recursion flows through fallback chains,
Certificates dance in connection lanes,
A config migration, clean and serene!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description clearly explains the root cause, symptom, and fix for the S2S dialback issue with self-signed certificates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@guusdk
Copy link
Copy Markdown
Member

guusdk commented May 6, 2026

@milne1282 I've raised a ticket for this change in https://igniterealtime.atlassian.net/browse/OF-3259

I've also added a couple of commits to this PR, that addresses similar issues with certificate-verification related properties. I'd love your feedback on those. Please refer to the individual commit messages for details.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionListener.java (1)

747-762: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Bug: oldValue retrieves from wrong method.

Line 749 calls verifyCertificateValidity() but should call acceptSelfSignedCertificates(). This causes the comparison on line 754 to be incorrect, and the log messages will report wrong old/new values for the self-signed certificate acceptance setting.

🐛 Proposed fix
     public void setAcceptSelfSignedCertificates( boolean accept )
     {
-        final boolean oldValue = verifyCertificateValidity();
+        final boolean oldValue = acceptSelfSignedCertificates();

         // Always set the property explicitly even if it appears the equal to the old value (the old value might be a fallback value).
         JiveGlobals.setProperty( type.getPrefix() + "certificate.accept-selfsigned", Boolean.toString( accept ) );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionListener.java`
around lines 747 - 762, The setter setAcceptSelfSignedCertificates currently
reads the old value from verifyCertificateValidity(), which is wrong; change it
to call acceptSelfSignedCertificates() to obtain the actual previous setting, so
the equality check and subsequent Log.debug messages report the correct old/new
state; keep the JiveGlobals.setProperty call and restart() behavior the same but
ensure comparisons and log formatting use acceptSelfSignedCertificates() as the
source of oldValue.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionListener.java`:
- Around line 747-762: The setter setAcceptSelfSignedCertificates currently
reads the old value from verifyCertificateValidity(), which is wrong; change it
to call acceptSelfSignedCertificates() to obtain the actual previous setting, so
the equality check and subsequent Log.debug messages report the correct old/new
state; keep the JiveGlobals.setProperty call and restart() behavior the same but
ensure comparisons and log formatting use acceptSelfSignedCertificates() as the
source of oldValue.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3d3b6635-cdbf-4a10-a5c4-d6f937da46eb

📥 Commits

Reviewing files that changed from the base of the PR and between d37b509 and 0bbf1e2.

📒 Files selected for processing (7)
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/ClientTrustManager.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/ServerStanzaHandler.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/ServerTrustManager.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/net/TLSStreamHandler.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/server/ServerDialback.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/session/ConnectionSettings.java
  • xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionListener.java

@guusdk
Copy link
Copy Markdown
Member

guusdk commented May 7, 2026

⚠️ Outside diff range comments (1)

xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionListener.java (1)> 747-762: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Bug: oldValue retrieves from wrong method.
Line 749 calls verifyCertificateValidity() but should call acceptSelfSignedCertificates(). This causes the comparison on line 754 to be incorrect, and the log messages will report wrong old/new values for the self-signed certificate acceptance setting.

This code review finding is something that is already being fixed in a different PR: #3308

milne1282 and others added 4 commits May 8, 2026 20:56
…rts accepted

ServerDialback.isEnabledForSelfSigned() reads the legacy property
xmpp.server.certificate.accept-selfsigned (TLS_ACCEPT_SELFSIGNED_CERTS),
but ConnectionListener.setAcceptSelfSignedCertificates() — which backs the
Admin Console UI checkbox — writes to the per-connection-type prefixed
property xmpp.socket.ssl.certificate.accept-selfsigned. These diverged when
per-type prefixed properties were introduced but the readers in ServerDialback
were not updated.

The consequence is that after a successful TLS handshake with a self-signed
peer certificate, LocalIncomingServerSession.getAvailableStreamFeatures() calls
isEnabledForSelfSigned(), gets false, and omits <db:dialback> from the post-TLS
<stream:features>. The connecting server then finds no usable authentication
mechanism and closes the connection. This causes all encrypted S2S connections
to fail silently when the only option is dialback, even if the operator has
enabled self-signed certificate acceptance via the UI.

Fix: check both property names in isEnabledForSelfSigned(), preserving full
backwards compatibility with installations that have the legacy property set.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…y configuration

In OF-946 refactor, connection configuration introduced per-type prefixed properties. However, not all usages of the legacy properties were migrated. As a result, some functionality still depends on the old properties while others use the new ones (sometimes even within related features) leading to inconsistent and incompatible behavior (e.g., server-to-server uses new properties, while Dialback relies on legacy ones).

This commit deprecates the legacy `xmpp.server.certificate.accept-selfsigned` and xmpp.client.certificate.accept-selfsigned` properties in favor of `ConnectionListener#acceptSelfSignedCertificates`.

Changes:
- Add fallback: the new configuration uses the legacy property if it is explicitly set.
- Migrate all remaining usages from the legacy property to the new configuration.

This ensures consistent behavior across all connection types and prevents configuration mismatches.
…s and unify configuration

In OF-946 refactor, connection configuration introduced per-type prefixed properties. However, not all usages of the legacy properties were migrated. As a result, some functionality still depends on the old properties while others use the new ones (sometimes even within related features) leading to inconsistent and incompatible behavior (e.g., server-to-server uses new properties, while Dialback relies on legacy ones).

This commit deprecates the legacy `xmpp.server.certificate.verify.validity` and `xmpp.client.certificate.verify.validity` properties in favor of `ConnectionListener#verifyCertificateValidity`.

Changes:
- Add fallback: the new configuration uses the legacy property if it is explicitly set.
- Migrate all remaining usages from the legacy property to the new configuration.

This ensures consistent behavior across all connection types and prevents configuration mismatches.
…rties for removal

`org.jivesoftware.openfire.net.ClientTrustManager` has been replaced by `org.jivesoftware.openfire.keystore.OpenfireX509TrustManager` at least a decade ago. It is unlikely that it's still being used.

These properties are used _exclusively_ by this old implementation. As that implementation isn't in use any more, these properties are effectively unused.

- `xmpp.client.certificate.verify`
- `xmpp.client.certificate.crl`
- `xmpp.client.certificate.verify.chain`
- `xmpp.client.certificate.verify.root`

This commit explicitly marks the `ClientTrustManager` as being deprecated, for removal in Openfire 5.2.0. I don't think there's much value in retaining the properties, as their functionality seems questionably specific. Apparently, it hasn't been missed in the last decade.

There properties above are specific to client connectivity.

For server connectivity, things are slightly different. There also exists `org.jivesoftware.openfire.net.ServerTrustManager` which also goes unused. It is unlikely that it's still begin used. This implementation, unlike its client-counterpart, does not (directly) use similar properties.

This commit explicitly marks the `ServerTrustManager` as being deprecated, for removal in Openfire 5.2.0.

The properties mentioned above have server-equivalents:
- `xmpp.server.certificate.verify`
- `xmpp.server.certificate.verify.chain`
- `xmpp.server.certificate.verify.root`

(`xmpp.server.certificate.crl` is not defined)

 Unlike the client properties, these server properties are used in other bits of code.

`xmpp.server.certificate.verify` (as constant `org.jivesoftware.openfire.session.ConnectionSettings.Server#TLS_CERTIFICATE_VERIFY`)
- appears to be used in `org.jivesoftware.openfire.net.SASLAuthentication` to assert if, for every server-to-server SASL authentication mechanism applied to incoming server-to-server connections, the peer's certificates should be validated. There's just one SASL mechanism for incoming server-to-server connections, which is EXTERNAL. Its implementation seems to unconditionally verify certificates in `org.jivesoftware.openfire.sasl.ExternalServerSaslServer` - the SASL mechanisms that we offer to server peers (in `org.jivesoftware.openfire.net.SASLAuthentication`) only offers EXTERNAL when the peer's certificates are unconditionally validated. In this path, the property doesn't seem to be useful.
- is used in `org.jivesoftware.openfire.net.ServerStanzaHandler` to populate a variable that is not used. In this path, the property does not seem to be useful either.
- is used in `org.jivesoftware.openfire.net.TLSStreamHandler` to configure a TLS Engine, specifically to check if a peer's certificate is wanted, or needed. `TLSStreamHandler` itself is used by `org.jivesoftware.openfire.server.ServerDialback` and `org.jivesoftware.openfire.net.SocketConnection` (which is documented to be used only for Server Dialback). Server Dialback is a mechanism used when SASL EXTERNAL (which is based on TLS certifiate validation) is unavailable. It seems unlikely that low-level configuration of TLS certificates is required (or even desired) for Server Dialback.

In all, `xmpp.server.certificate.verify` seems to be largely unused.

`xmpp.server.certificate.verify.chain` (as constant `org.jivesoftware.openfire.session.ConnectionSettings.Server#TLS_CERTIFICATE_CHAIN_VERIFY`)
- is used in `org.jivesoftware.openfire.net.ServerStanzaHandler` to populate a variable that is not used. In this path, the property does not seem to be useful.
- is used in `org.jivesoftware.openfire.net.TLSStreamHandler` to configure a TLS Engine, specifically to check if a peer's certificate is wanted, or needed. TLSStreamHandler itself is used by `org.jivesoftware.openfire.server.ServerDialback` and `org.jivesoftware.openfire.net.SocketConnection` (which is documented to be used only for Server Dialback). Server Dialback is a mechanism used when SASL EXTERNAL (which is based on TLS certifiate validation) is unavailable. It seems unlikely that low-level configuration of TLS certificates is required (or even desired) for Server Dialback.

In all, `xmpp.server.certificate.verify.chain` seems to be largely unused.

`xmpp.server.certificate.verify.root` (as constant `org.jivesoftware.openfire.session.ConnectionSettings.Server#TLS_CERTIFICATE_ROOT_VERIFY`)
- Only defined as a constant, but the constant is not used.

I believe all of the above is reason to phase out all of these properties:
- `xmpp.client.certificate.verify`
- `xmpp.client.certificate.crl`
- `xmpp.client.certificate.verify.chain`
- `xmpp.client.certificate.verify.root`
- `xmpp.server.certificate.verify`
- `xmpp.server.certificate.verify.chain`
- `xmpp.server.certificate.verify.root`

Unlike the properties `xmpp.server.certificate.verify.validity`, `xmpp.client.certificate.verify.validity`, `xmpp.server.certificate.accept-selfsigned` and xmpp.client.certificate.accept-selfsigned` that have been deprecated in earlier commits, but have been replaced by `ConnectionListener` functionality, I see little value in introducing new functionality in `ConnectionListener` to match the properties above.

In this commit, I have marked the constants that define the properties above as being deprecated, for removal in Openfire 5.2.0. Properties for which no constant is defined are used in code that is already marked for removal, so they'll disappear automatically.
@guusdk guusdk force-pushed the fix/s2s-selfsigned-dialback-property branch from 0bbf1e2 to d750017 Compare May 8, 2026 18:57
@guusdk
Copy link
Copy Markdown
Member

guusdk commented May 8, 2026

I've rebased this to the latest HEAD of the Main branch, which has some improvements to the CI workflow. Hopefully, tests are more stable now.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants