]
RH Bugzilla Integration updated WFLY-1924:
------------------------------------------
Bugzilla Update: Perform
Bugzilla References:
An EJB on a WildFly server can't call another bean on a second
server with remoting and SSL
-------------------------------------------------------------------------------------------
Key: WFLY-1924
URL:
https://issues.jboss.org/browse/WFLY-1924
Project: WildFly
Issue Type: Bug
Security Level: Public(Everyone can see)
Components: EJB, Remoting, Security
Affects Versions: 8.0.0.Alpha4
Environment: WildFly 8.0.0.Beta1-SNAPSHOT from Do 22. Aug 2013, 07:48 UTC
on Linux with Java 1.7.0_25-b15
Reporter: Bernd Koecke
Assignee: jaikiran pai
Fix For: 8.0.0.Beta1
I configured two WildFly server, one is the service provider (server), the other one the
consumer (client). An EJB on the consumer server tries to call an EJB on the provider
server and the remoting connection is secured by SSL. But it doesn't work. I can see
the negotiation of the cipher suites and then the communication stops. I get a
{{javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?}}
on the provider side. A JavaSE client can call the service provider, but only when
SSL_SARTTLS is not set. My current setup is:
subsystem undertow, default-server:
{code:xml}
<https-listener name="defaults" socket-binding="https"
security-realm="HttpsRealm"/>
{code}
subsystem ejb3:
{code:xml}
<remote connector-ref="https-remoting-connector"
thread-pool-name="default"/>
{code}
Output on the service provider side when the communication stops:
{noformat}
[stdout] (default I/O-3) Using SSLEngineImpl.
[stdout] (default I/O-3) Ignoring unavailable cipher suite: ...
*** 13 lines more ***
[stdout] (default I/O-3) Allow unsafe renegotiation: false
[stdout] (default I/O-3) Allow legacy hello messages: true
[stdout] (default I/O-3) Is initial handshake: true
[stdout] (default I/O-3) Is secure renegotiation: false
[stdout] (default I/O-3) default I/O-3, fatal error: 80: problem unwrapping net record
[stdout] (default I/O-3) javax.net.ssl.SSLException: Unrecognized SSL message, plaintext
connection?
[stdout] (default I/O-3) default I/O-3, SEND TLSv1 ALERT: fatal, description =
internal_error
[stdout] (default I/O-3) default I/O-3, WRITE: TLSv1 Alert, length = 2
[stdout] (default I/O-3) default I/O-3, called closeOutbound()
[stdout] (default I/O-3) default I/O-3, closeOutboundInternal()
[stdout] (default I/O-3) [Raw write]: length = 7
[stdout] (default I/O-3) 0000: 15 03 01 00 02 02 50
......P
{noformat}
WildFly consumer config
subsystem remoting, outbound connections:
{code:xml}
<remote-outbound-connection name="provider-one-connection"
outbound-socket-binding-ref="provider-ejb"
security-realm="ProviderOneRealm" protocol="https-remoting">
<properties>
<property name="SASL_POLICY_NOANONYMOUS" value="false"/>
</properties>
</remote-outbound-connection>
{code}
The realms contain the key- and truststores and all passwords are configured.
The reason for the communication problem comes from the following code.
The service consumer (or client) WildFly has a remote-outbound-connection in the remoting
subsystem config which results in an
{{org.jboss.as.remoting.RemoteOutboundConnectionService}}. There is a {{connect()}} method
which contains the lines:
{code:java}
OptionMap.Builder builder = OptionMap.builder();
builder.addAll(this.connectionCreationOptions);
builder.set(SASL_POLICY_NOANONYMOUS, Boolean.FALSE);
builder.set(SASL_POLICY_NOPLAINTEXT, Boolean.FALSE);
builder.set(Options.SASL_DISALLOWED_MECHANISMS, Sequence.of(JBOSS_LOCAL_USER));
builder.set(Options.SSL_ENABLED, true);
builder.set(Options.SSL_STARTTLS, true);
return endpoint.connect(uri, builder.getMap(), callbackHandler, sslContext);
{code}
My configuration comes from {{this.connectionOptions}} and is overwritten by the
defaults. The service consumer will open the connection with {{SSL_STARTTLS==true}}.
The service provider (or server) WildFly uses an https-listener from the undertow
subsystem. Which generates an {{org.wildfly.extension.undertow.HttpsListenerService}}.
Method {{startListening(XnioWorker worker,...)}} has the following code:
{code:java}
protected void startListening(XnioWorker worker, InetSocketAddress socketAddress,
ChannelListener<AcceptingChannel<StreamConnection>> acceptListener) throws
IOException {
SSLContext sslContext = securityRealm.getValue().getSSLContext();
Builder builder = OptionMap.builder().addAll(SERVER_OPTIONS);
builder.set(UndertowOptions.MAX_ENTITY_SIZE, maxUploadSize);
if
(securityRealm.getValue().getSupportedAuthenticationMechanisms().contains(AuthMechanism.CLIENT_CERT))
{
builder.set(SSL_CLIENT_AUTH_MODE, REQUESTED);
}
builder.set(Options.USE_DIRECT_BUFFERS,true);
OptionMap combined = builder.getMap();
XnioSsl xnioSsl = new JsseXnioSsl(worker.getXnio(), combined, sslContext);
sslServer = xnioSsl.createSslConnectionServer(worker, socketAddress,
(ChannelListener) acceptListener, combined);
sslServer.resumeAccepts();
UndertowLogger.ROOT_LOGGER.listenerStarted("HTTPS", getName(),
socketAddress);
}
{code}
The OptionMap {{combined}} is used for the {{JsseXnioSsl}} and I can't see a way how
to add my own configuration options. The result is that {{SSL_STARTTLS}} is undefined and
in {{JsseXnioSsl}} has a method {{connectSsl}} which calls {{openSslConnection}}. There is
an event handler build which calls:
{code:java}
new JsseSslStreamConnection(connection, JsseSslUtils.createSSLEngine(sslContext,
optionMap, destination), socketBufferPool, applicationBufferPool,
optionMap.get(Options.SSL_STARTTLS, false));
{code}
This sets the flag {{startTls}} of the constructor to false and the member variable
{{tls}} in {{org.xnio.ssl.JsseSslStreamConnection}} to true. And when I understand it
right, will then the consumer start unencrypted and will only switch to TLS when it is
told todo so. But the service provider expectes, because of {{tls==true}}, an encrypted
connection right from the beginning. And this generates the above error message/exception.
I can reproduce this by using a JavaSE client to call the service provider. This works
well when I don't set {{SSL_STARTTLS}} on the client side. But when I set it to
{{true}} I get the same behavior like when the client is another WildFly instance.
[~ctomc] said that on the consumer side in the {{connect()}} method the
{{builder.addAll(...)}} should be moved to the end after setting the defaults. Thats the
reason for this issue.
With this solution I can switch off {{SSL_STARTTLS}} on the consumer(client) side.
Another additional possibility could be to make the provider (server) side configurable
that the hard coded options can be overwritten. But I don't know if this fits in the
original design.
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: