How can I make a Camel/Netty4 SSL Client initiate a handshake? - java

I have a server that I wish to connect to via SSL, and then listen for data. I have a Camel route set up (via Spring) with a Netty4 endpoint as follows:
<camel:endpoint id="sslEndpoint" uri="netty4:tcp://{{server.host}}:{{server.port}}">
<camel:property key="clientMode" value="true" />
<camel:property key="needClientAuth" value="true" />
<camel:property key="sync" value="false" />
<camel:property key="ssl" value="true" />
<camel:property key="keyStoreResource" value="file:{{server.keystore}}" />
<camel:property key="trustStoreResource" value="file:{{server.truststore}}" />
<camel:property key="passphrase" value="{{server.passphrase}}" />
</camel:endpoint>
The route is configured in Java with this endpoint as the from part of the route:
public class MyRoute extends RouteBuilder {
#Override
public void configure() {
from("ref:sslEndpoint")
.to("log:MyLog?level=DEBUG");
}
}
By default a from endpoint will create a NettyConsumer, which acts as a server, hence specifying clientMode=true on the endpoint. This is honoured when using a plain TCP connection (it does indeed connect as a client, and receive data sent to it from the server). However, when using SSL it doesn't start off the SSL Handshake, meaning the server doesn't send out any data.
I have rooted through the Camel Netty4 code, and the key issue is in DefaultServerInitializerFactory where a new SSL Connection is configured - the SSLEngine has a hard-coded setUseClientMode(false). Sticking a breakpoint here and changing the call to true does indeed cause Netty to connect to the server, initiate the SSL handshake, and start consuming received data.
So my question is twofold:
How can I best resolve this issue and make the SSL Client initiate a handshake? Have I just missed something obvious?
Is this a bug in Camel/Netty4, as it would appear to me that the SSL connection should honour the clientMode property of the endpoint?

Related

MSSQL - Connection String

I have made a project using Entity Framework in Visual Studio. I have following connection string
<connectionStrings>
<add name="HospitalManagementEntities" connectionString="metadata=res://*/HospitalEntities.csdl|res://*/HospitalEntities.ssdl|res://*/HospitalEntities.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=HospitalManagement;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
<add name="HospitalManagementContext" connectionString="metadata=res://*/HospitalManagement.csdl|res://*/HospitalManagement.ssdl|res://*/HospitalManagement.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=HospitalManagement;integrated security=True;multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
It connects with the mssql.
But when I try to connect with same database from Java - Hibernate/Spring it gives me error.
UDP Connection String
<bean id="dataSourceMain"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://localhost\SQLEXPRESS;databaseName=HospitalManagement;integratedSecurity=true;Trusted_Connection=yes;" />
</bean>
Error
Could not obtain connection to query metadata : The connection to the
host localhost, named instance sqlexpress failed. Error:
"java.net.SocketTimeoutException: Receive timed out". Verify the
server and instance names and check that no firewall is blocking UDP
traffic to port 1434. For SQL Server 2005 or later, verify that the
SQL Server Browser Service is running on the host.
TCP Connection String
<bean id="dataSourceMain"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://localhost;databaseName=HospitalManagement;integratedSecurity=true;Trusted_Connection=yes;" />
</bean>
Error
Could not obtain connection to query metadata : The TCP/IP connection
to the host localhost, port 1433 has failed. Error: "Connection
refused: connect. Verify the connection properties. Make sure that an
instance of SQL Server is running on the host and accepting TCP/IP
connections at the port. Make sure that TCP connections to the port
are not blocked by a firewall.".
Ports Info
Netstat
Questions
As you can see that both udp and tcp ports are blocked/inactive.
1) So how Visual Studio managed to get connected to MSSQL ?
2) What protocol does Entity framework uses in above case ?
3) Is there a way to connect to Mssql in Java - Hibernate/Spring, bypassing the firewall or udp/tcp requirements ?
P.S. I have no admin rights. So for now I can't enable TCP/IP port.

Wcf with client certificate authentication doesn't work with soapui

I've a wcf service with basicHttpBinding, message security mode and certificate client credential type. I can consume this service via wcf client, but this service has to be used also in another system with a java client. I'm testing with soapui, but I obtain empty response or a security message error. I've tried variuos soapui configuration to load client certificate, but none of these worked. I exposed the service via http (non https) and this is the server wcf configuration:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicEndPoint" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8"
transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"/>
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="customBehavior">
<clientCredentials>
<clientCertificate findValue="ClientSide" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
<serviceCertificate>
<defaultCertificate findValue="ServerSide" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
<authentication certificateValidationMode="PeerOrChainTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="http://localhost:8080/WebServices/ExternalServices.svc"
behaviorConfiguration="customBehavior" binding="basicHttpBinding"
bindingConfiguration="basicEndPoint" contract="ServiceReference1.IExternalServices"
name="BasicHttpBinding_IExternalServices" >
<identity>
<certificateReference findValue="ServerSide" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
<dns value="ServerSide"/>
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</client>
</system.serviceModel>
What's wrong in this settings?
Thanks in advance
I'm not an WCF expert (even not a user :P) but based on configuration:
<endpointBehaviors>
<behavior name="customBehavior">
<clientCredentials>
<clientCertificate findValue="ClientSide" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
<serviceCertificate>
<defaultCertificate findValue="ServerSide" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
<authentication certificateValidationMode="PeerOrChainTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
Seems that in order to hit your server endpoint you must present certificate client credentials.
So to invoke your service from SOAPUI you could do two things, first expose your service using https in order to be available for a client to present the certificate credentials. And second configure SOAPUI as follow to send the client certificate to the endpoint:
From the menu select File > Preferences, and then the SSL settings. In this panel select a keystore which contains the client key and certificate valid for the service and put the keystore password, optionally mark the required client authentication:
NOTE: Based on your configuration:
<clientCertificate findValue="ClientSide"
x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
A valid client certificate must be an end entity certificate issued by on the certificate authorities located in the Windows local keystore of your server.
I had hard time setting up SOAPUI for WCF testing with Client Certificate Authentication. Finally I got it work.
Faced different issues like: SNI support issues, unsigned 'To' Header Getting WCF to accept unsigned 'To' Header and other.
I would recommend to switch on WCF tracing and you can get detailed error information on the server: https://msdn.microsoft.com/en-us/library/ms732023(v=vs.110).aspx so it can be easily troubleshooted.

Mq Connection error 2058

I have a spring core application with config below.
I'm using UserCredentialsConnectionFactoryAdapter, MQQueueConnectionFactory and jms-listener.
<jms:listener-container container-type="default"
connection-factory="userConnectionFactory" acknowledge="auto">
<jms:listener destination="${QUEUE_NAME_IN_GEN}" ref="messageListener"
method="onMessage" />
</jms:listener-container>
<bean id="userConnectionFactory"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory">
<ref bean="mqConnectionFactory" />
</property>
<property name="username" value="${MQ_USER_ID}" />
</bean>
<bean id="mqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="hostName">
<value>${MQ_HOST_NAME}</value>
</property>
<property name="port">
<value>${MQ_PORT}</value>
</property>
<property name="queueManager">
<value>${QUEUE_MANAGER}</value>
</property>
<property name="transportType">
<value>1</value>
</property>
</bean>
on application startup, listener stars perfectly one one machine.
when I try with same artifacts on a different server, listener fails to start with following error:
[org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] ERROR org.springframework.jms.listener.DefaultMessageListenerContainer.refreshConnectionUntilSuccessful(DefaultMessageListenerContainer.java:909) - Could not refresh JMS Connection for destination 'R.ABCDEF' - retrying in 5000 ms. Cause: MQJMS2005: failed to create MQQueueManager for 'myhost:dev'; nested exception is com.ibm.mq.MQException: MQJE001: An MQException occurred: Completion Code 2, Reason 2058
MQJE036: Queue manager rejected connection attempt
To figure out if it's something to do with Unix account privilege issue on the second server, I wrote a simple MQ Client application. This program can connect to this queue manager and read messages from it.
What else could be wrong?
A 2058 suggests that the queue manager name is incorrect. According to the technote from IBM that's the most common cause, however there are others.
The following extract is taken from this technote:
Ensure that the queue manager name is specified correctly on:
MQCONN API calls
QREMOTE object definitions
Client connection channel definitions
Debugging QCF, TCF, or Client connection problems are much more complex.
Ensure that the connection request is routed to the intended machine and queue manager.
Verify that the listener program is starting the channel on the correct queue manager.
Ensure that the specifications for the client environment variables are correct.
mqserver
mqchllib
mqchltab
If you are using a client channel table (amqclchl.tab), then verify that your client connection channel definition has the correct queue manager name (QMNAME) specified.
Specify the correct queue manager name.
Correct channel routing problems.
Correct inetd listener configuration problems.
Correct client related configuration problems.

Mule truststore and keystore

if I create a trust-store and keystore for https inbound endpoints, my other https outbound endpoints start throwing exceptions.
An example is, if I create a HTTPS inbound enpoint connector like below,
<https:connector name="MuleHTTPS" cookieSpec="netscape"
validateConnections="true" sendBufferSize="0" receiveBufferSize="0"
receiveBacklog="0" clientSoTimeout="${APP.TIMEOUT}" serverSoTimeout="${APP.TIMEOUT}"
socketSoLinger="0" doc:name="MuleHTTPS">
<https:tls-key-store path="${HONDA.HTTPS.KEYSTORE}"
keyPassword="${HTTPS.KEYSTORE.PASSWORD}" storePassword="${HTTPS.KEYSTORE.PASSWORD}" />
<https:tls-server path="${HONDA.HTTPS.KEYSTORE}" explicitOnly="true" storePassword="${HTTPS.KEYSTORE.PASSWORD}"/>
</https:connector>
The sqs inbound starts throwing peer not authenticated error. The config is
<sqs:config name="ReceiverAmazonSQS" accessKey="${AMAZON.ACCESS.KEY}"
secretKey="${AMAZON.SECRET.KEY}" queueName="${AMAZON.QUEUE.NAME}"
doc:name="SenderAmazonSQS" queueUrl="${AMAZON.QUEUE.URL}">
</sqs:config>
<sqs:receive-messages config-ref="ReceiverAmazonSQS"
doc:name="Receive Messages"/>
What am I missing?
If there is only one HTTPS connector defined in a mule application, by default all the https endpoints, which do not have any connector defined, use the same connector. (Unless you define one more HTTPS connector and specify it in endpoint). This is the case with any transport in mule.

Spring Integration - FTP outbound gateway LS always empty on *unix

I have a simple ftp outbound gateway configured for ls, get, rm
<int-ftp:outbound-gateway id="gatewayLS"
cache-sessions="false"
session-factory="incomingCachingSessionFactory"
request-channel="inboundChannel"
command="ls"
command-options="-1"
expression="'${ftp.pull.remote.directory}'"
reply-channel="toSplitter" />
<channel id="toSplitter">
<interceptors>
<wire-tap channel="logger" />
</interceptors>
</channel>
<logging-channel-adapter id="logger"
log-full-message="true" level="DEBUG" />
<splitter id="splitter" input-channel="toSplitter"
output-channel="toGet" />
<int-ftp:outbound-gateway id="gatewayGET"
cache-sessions="false"
local-directory="${ftp.pull.local.directory}"
session-factory="incomingCachingSessionFactory"
request-channel="toGet"
reply-channel="downloadedFileChannel"
command="get"
command-options="-P"
expression="headers['file_remoteDirectory'] + '/' + payload" />
this works perfectly on my development windows box, connecting to multiple different FTP servers.
and my log outputs expected
DEBUG: org.springframework.integration.ftp.session.DefaultFtpSessionFactory - Connected to server [ftp.domain.com:21]
DEBUG: org.springframework.integration.ftp.gateway.FtpOutboundGateway - handler 'org.springframework.integration.ftp.gateway.FtpOutboundGateway#0' sending reply Message: [Payload=[test_file.zip]][Headers={timestamp=1343143242030, id=56758ef9-57e5-43d6-b8b7-c36539d9fd0d, file_remoteDirectory=/images/}]
the time bewteen the "Connected to server" and "sending reply Message" is also pretty much instantaneous
however, once deployed to 2x Centos servers (5.8 and 6.2), the reply channel of the LS is always emtpy
e.g.
DEBUG: org.springframework.integration.ftp.session.DefaultFtpSessionFactory - Connected to server [ftp.domain.com:21]
DEBUG: org.springframework.integration.ftp.gateway.FtpOutboundGateway - handler 'org.springframework.integration.ftp.gateway.FtpOutboundGateway#0' sending reply Message: [Payload=[]][Headers={timestamp=1343143961046, id=31759d6f-201e-4028-8943-0a68ae64db81, file_remoteDirectory=/images/}]
the time between the "Connected to server" and "sending reply Message" is also abnormally long.
some more info:
all 3 machines are using maven to build the WAR from the same code base.
the 2 centos machines are in different datacentres
I have tried multiple different unrelated FTP servers, with the same results
there are definately files on the ftp server
the ftp servers are accessable on the centos boxes, confirmed using "ncftp" and "ftp"
I know this post is pretty vague, but it is driving me nuts. any thoughts greatly appreciated
I had to set <property name="clientMode" value="2" /> on my DefaultFtpSessionFactory

Categories