title: ActiveMQ mutual SSL authentication
body: <p>I'm trying to set up ActiveMQ for mutual authentication, that the client will need a certificate in order to pass messages to the broker. I created a keystore and a truststore on the broker and exported a certificate that was copied to the client. On the client side I did the same, although I am using NMS so I am only using the exported certificate, which I added to the broker's truststore.  I also added the certificate's to the other's Local Computer Trusted Root Certificates.<br>
  The broker's configuration has this:  </p>
  
  <pre><code>&lt;transportConnectors&gt;  
    &lt;transportConnector name="ssl" uri="ssl://0.0.0.0:61616"/&gt;  
  &lt;/transportConnectors&gt;  
  &lt;sslContext&gt;  
    &lt;sslContext keyStore="file:${activemq.base}/conf/keystore.jks"  
      keyStorePassword="ksPass"  
      trustStore="file:${activemq.base}/conf/shared.ks"  
      trustStorePassword="ksPass"/&gt;  
  &lt;/sslContext&gt;  
  &lt;plugins&gt;  
   &lt;jaasCertificateAuthenticationPlugin configuration="CertLogin" /&gt;  
  &lt;/plugins&gt;  
  </code></pre>
  
  <p>amq service <em>wrapper.conf</em> has<br>
  <code>wrapper.java.additional.8=-Djava.security.auth.login.config="%ACTIVEMQ_CONF%/login.config"</code>  </p>
  
  <p>${activemq.base}/conf/login.config  </p>
  
  <pre><code>CertLogin {
   org.apache.activemq.jaas.TextFileCertificateLoginModule required
   debug=true
   org.apache.activemq.jaas.textfiledn.user="users.properties"
   org.apache.activemq.jaas.textfiledn.group="groups.properties";
  };  
  </code></pre>
  
  <p>${activemq.base}/conf/users.properties has  </p>
  
  <pre><code>user=CN=nms.client.170,\ OU=IT,\ O=MyOrg,\ L=Oslo,\ S=Oslo,\ C=NO  
  </code></pre>
  
  <p>${activemq.base}/conf/groups.properties has  </p>
  
  <pre><code>admins=system  
  users=system,user    
  </code></pre>
  
  <p>In the NMS client's appSettings I use this to connect:  </p>
  
  <pre><code>&lt; add key="jms.uri" value="ssl://brokeraddress.in.hosts:61616?needClientAuth=true&amp;amp;wantClientAuth=true&amp;amp;transport.clientCertSubject=nms.client.170&amp;amp;transport.clientCertPassword=ksClientPw&amp;amp;transport.clientCertFilename=C:\TestClient\client170.crt" /&gt;    
  </code></pre>
  
  <p>If I don't have the jaasCertificateAuthenticationPlugin in the broker I can connect via ssl, but with it (which is what I had in mind) I get an error, it fails in <em>Apache.NMS.ActiveMQ.Connection</em><br>
      <code>// Send the connection and see if an ack/nak is returned.<br>
      Response response = transport.Request(this.info, this.RequestTimeout);</code><br>
  Gets an ExeptionResponse: "java.lang.SecurityException: Unable to authenticate transport without SSL certificate."  </p>
  
  <p>The trace shows:  </p>
  
  <pre><code>10:19:16,479 INFO  Client.MyTrace - BrokerUri set = ssl://brokeraddress.in.hosts:61616?transport.clientcertpassword=ksClient&amp;transport.clientcertsubject=nms.client.170&amp;needclientauth=true&amp;wantclientauth=true&amp;transport.clientcertfilename=C:\TestClient\client170.crt  
  10:19:16,492 DEBUG Client.MyTrace - SetProperties called with target: ConnectionFactory, and prefix: connection.  
  10:19:16,492 DEBUG Client.MyTrace - SetProperties called with target: ConnectionFactory, and prefix: nms.  
  10:19:16,495 INFO  Client.MyTrace - Connecting to: ssl://brokeraddress.in.hosts:61616/?transport.clientcertpassword=ksClient&amp;transport.clientcertsubject=nms.client.170&amp;needclientauth=true&amp;wantclientauth=true&amp;transport.clientcertfilename=C:\TestClient\client170.crt  
  10:19:16,497 DEBUG Client.MyTrace - Searching Assembly: Apache.NMS.ActiveMQ for factory of the id: ssl  
  10:19:16,549 DEBUG Client.MyTrace - Found the Factory of type Apache.NMS.ActiveMQ.Transport.Tcp.SslTransportFactory for id: ssl  
  10:19:16,552 DEBUG Client.MyTrace - Opening socket to: brokeraddress.in.hosts on port: 61616  
  10:19:16,554 DEBUG Client.MyTrace - Connected to brokeraddress.in.hosts:61616 using InterNetwork protocol.  
  10:19:16,562 DEBUG Client.MyTrace - Creating new instance of the SSL Transport.  
  10:19:16,564 DEBUG Client.MyTrace - Creating Inactivity Monitor: 1  
  10:19:16,677 DEBUG Client.MyTrace - Authorizing as Client for Server: brokeraddress.in.hosts  
  10:19:16,679 DEBUG Client.MyTrace - Attempting to load Client Certificate from file := C:\TestClient\client170.crt  
  10:19:16,682 DEBUG Client.MyTrace - Loaded Client Certificate := [Subject]  CN=nms.client.170, OU=IT, O=MyOrg, L=Oslo, S=Oslo, C=NO [Issuer]  CN=nms.client.170, OU=IT, O=MyOrg, L=Oslo, S=Oslo, C=NO  
  10:19:16,684 DEBUG Client.MyTrace - Client is selecting a local certificate from 1 possibilities.  
  10:19:16,684 DEBUG Client.MyTrace - Client has selected certificate with Subject = CN=nms.client.170, OU=IT, O=MyOrg, L=Oslo, S=Oslo, C=NO  
  10:19:16,969 DEBUG Client.MyTrace - ValidateServerCertificate: Issued By CN=brokeraddress.in.hosts, OU=DataCom, O=MyOrg, L=Oslo, S=Oslo, C=NO  
  10:19:16,969 DEBUG Client.MyTrace - Server is Authenticated = True  
  10:19:16,970 DEBUG Client.MyTrace - Server is Encrypted = True  
  10:19:16,978 DEBUG Client.MyTrace - InactivityMonitor[1]: Read Check time interval: 30000  
  10:19:16,978 DEBUG Client.MyTrace - InactivityMonitor[1]: Initial Delay time interval: 10000  
  10:19:16,985 DEBUG Client.MyTrace - InactivityMonitor[1]: Write Check time interval: 10000  
  10:19:19,017 DEBUG Client.MyTrace - Exception received in the Inactivity Monitor: Unable to read beyond the end of the stream.  
  10:19:19,019 DEBUG Client.MyTrace - InactivityMonitor[1].Runner: Task Runner Shut Down  
  10:19:19,019 DEBUG Client.MyTrace - InactivityMonitor[1]: Stopped Monitor Threads.  
  10:19:19,032 DEBUG Client.MyTrace - Connection[ID:EJPB-56409-635193299565662525-1:0]: Async exception with no exception listener: System.IO.EndOfStreamException: Unable to read beyond the end of the stream.  
   System.IO.BinaryRe.FillBuffer(Int32 numBytes)  
   System.IO.BinaryRe.ReadInt32()  
   Apache.NMS.Util.EnBinaryReader.ReadInt32() in c:\dev\NMS\src\main\csharp\Util\EndianBinaryReader.cs:line 135  
   Apache.NMS.ActiveMenWire.OpenWireFormat.Unmarshal(BinaryReader dis) in c:\dev\NMS.ActiveMQ\src\main\csharp\OpenWire\OpenWireFormat.cs:line 228  
   Apache.NMS.ActiveMansport.Tcp.TcpTransport.ReadLoop() in c:\dev\NMS.ActiveMQ\src\main\csharp\Transport\Tcp\TcpTransport.cs:line 295  
  10:19:19,035 DEBUG Client.MyTrace - TransportFilter disposing of next Transport: MutexTransport  
  10:19:19,035 DEBUG Client.MyTrace - TransportFilter disposing of next Transport: WireFormatNegotiator  
  10:19:19,036 DEBUG Client.MyTrace - TransportFilter disposing of next Transport: InactivityMonitor  
  10:19:19,036 DEBUG Client.MyTrace - InactivityMonitor[1]: Stopped Monitor Threads.  
  10:19:19,037 DEBUG Client.MyTrace - TransportFilter disposing of next Transport: SslTransport  
  10:19:19,071 INFO  Client.MyTrace - Connection[ID:SUSSDEV2-56409-635193299565662525-1:0]: Closing Connection Now.  
  10:19:19,073 DEBUG Client.MyTrace - Connection[ID:SUSSDEV2-56409-635193299565662525-1:0]: Disposing of the Transport.  
  10:19:19,073 DEBUG Client.MyTrace - InactivityMonitor[1]: Stopped Monitor Threads.  
  </code></pre>
  
  <p>and in the broker it says:  </p>
  
  <pre>
  INFO | jvm 1 | 10:18:20 | WARN | Failed to add Connection ID:EJPB-56409-635193299565662525-1:0, reason: java.lang.SecurityException: Unable to authenticate transport without SSL certificate.  
  INFO | jvm 1 | 10:18:22 | INFO | Stopping tcp://192.168.5.170:56408 because Failed with SecurityException: Unable to authenticate transport without SSL certificate.  
  </pre>
  
  <p>Ok, what am I missing?  It says "transport without SSL certificate", but it selects it during the client's connection and it is in both the broker's truststore and Root Certs.</p>
  
  <p>Using NMS 1.6.0 and activeMQ 5.8.0.<br>
  I also tried a simple client in java with the same result.  </p>
  
  <pre>
  Exception in thread "main" javax.jms.JMSException: Unable to authenticate transport without SSL certificate.  
      at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:49)  
      at org.apache.activemq.ActiveMQConnection.syncSendPacket  (ActiveMQConnection.java:1295)  
      at org.apache.activemq.ActiveMQConnection.ensureConnectionInfoSent  (ActiveMQConnection.java:1392)  
      at org.apache.activemq.ActiveMQConnection.start(ActiveMQConnection.java:504)  
      at com.atest.jms.Client.main(Client.java:69)  
  Caused by: java.lang.SecurityException: Unable to authenticate transport without SSL certificate.  
      at org.apache.activemq.security.JaasCertificateAuthenticationBroker.addConnection(JaasCertificateAuthenticationBroker.java:74)  
      at org.apache.activemq.broker.MutableBrokerFilter.addConnection(MutableBrokerFilter.java:91)  
      at org.apache.activemq.broker.TransportConnection.processAddConnection(TransportConnection.java:766)  
      at org.apache.activemq.broker.jmx.ManagedTransportConnection.processAddConnection(ManagedTransportConnection.java:79)  
      at org.apache.activemq.command.ConnectionInfo.visit(ConnectionInfo.java:139)  
      at org.apache.activemq.broker.TransportConnection.service(TransportConnection.java:329)  
      at org.apache.activemq.broker.TransportConnection$1.onCommand(TransportConnection.java:184)  
      at org.apache.activemq.transport.MutexTransport.onCommand(MutexTransport.java:50)  
      at org.apache.activemq.transport.WireFormatNegotiator.onCommand(WireFormatNegotiator.java:113)  
      at org.apache.activemq.transport.AbstractInactivityMonitor.onCommand(AbstractInactivityMonitor.java:288)  
      at org.apache.activemq.transport.TransportSupport.doConsume(TransportSupport.java:83)  
      at org.apache.activemq.transport.tcp.SslTransport.doConsume(SslTransport.java:91)  
      at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:214)  
      at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:196)  
      at java.lang.Thread.run(Unknown Source)    
  </pre>
  
  <p>Anyone has any ideas? Thanks.  </p>
  
  <h1>Edit nov 12th</h1>
  
  <p>Ok, I tried again. I see I hadn't added to the broker's  transportConnector ssl:  </p>
  
  <pre><code>&lt;transportConnector name="ssl" uri="ssl://0.0.0.0:61616?needClientAuth=true"/&gt;  
  </code></pre>
  
  <p>I tried the java client and it could send, but I'm still getting error for the NMS client (same config):  </p>
  
  <pre><code>15:28:14,044 ERROR Test_DataCom.MyTrace - Exception: A call to SSPI failed, see inner exception.
  15:28:14,045 ERROR Test_DataCom.MyTrace - Inner exception: An unknown error occurred while processing the certificate
  15:28:14,045 ERROR Test_DataCom.MyTrace - Authentication failed - closing the connection.  
  </code></pre>
  
  <p>and at the broker I get null cert chain  </p>
  
  <pre><code>INFO | jvm 1 | 15:28:13 | ERROR | Could not accept connection from tcp://192.168.50.170:61978: javax.net.ssl.SSLHandshakeException: null cert chain
  </code></pre>
  
  <p>I have the certs in each other's truststore and Local Computer Trusted Root CA... what more is needed? Where should it find the cert chain for self signed certs if not there?</p>