You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by jo...@apache.org on 2011/02/02 17:00:52 UTC

svn commit: r1066508 - in /qpid/trunk/qpid/cpp: include/qpid/client/ src/qpid/client/ src/qpid/client/amqp0_10/ src/qpid/sys/ssl/ src/tests/

Author: jonathan
Date: Wed Feb  2 16:00:51 2011
New Revision: 1066508

URL: http://svn.apache.org/viewvc?rev=1066508&view=rev
Log:
Resolves QPID-3031. Allows client connection options to specify an SSL cert-name.

Modified:
    qpid/trunk/qpid/cpp/include/qpid/client/ConnectionSettings.h
    qpid/trunk/qpid/cpp/src/qpid/client/ConnectionSettings.cpp
    qpid/trunk/qpid/cpp/src/qpid/client/SslConnector.cpp
    qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
    qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
    qpid/trunk/qpid/cpp/src/qpid/sys/ssl/SslSocket.cpp
    qpid/trunk/qpid/cpp/src/qpid/sys/ssl/SslSocket.h
    qpid/trunk/qpid/cpp/src/tests/ssl_test

Modified: qpid/trunk/qpid/cpp/include/qpid/client/ConnectionSettings.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/include/qpid/client/ConnectionSettings.h?rev=1066508&r1=1066507&r2=1066508&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/include/qpid/client/ConnectionSettings.h (original)
+++ qpid/trunk/qpid/cpp/include/qpid/client/ConnectionSettings.h Wed Feb  2 16:00:51 2011
@@ -122,6 +122,11 @@ struct ConnectionSettings {
      * layer. 0 means no security layer allowed.
      */
     unsigned int maxSsf;
+    /**
+     * SSL cert-name for the connection. Overrides global SSL
+     * settings. Used only when a client connects to the broker.
+     */
+    std::string sslCertName;
 };
 
 }} // namespace qpid::client

Modified: qpid/trunk/qpid/cpp/src/qpid/client/ConnectionSettings.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/client/ConnectionSettings.cpp?rev=1066508&r1=1066507&r2=1066508&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/client/ConnectionSettings.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/client/ConnectionSettings.cpp Wed Feb  2 16:00:51 2011
@@ -7,9 +7,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *   http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -30,7 +30,7 @@ namespace client {
 
 ConnectionSettings::ConnectionSettings() :
     protocol("tcp"),
-    host("localhost"), 
+    host("localhost"),
     port(5672),
     locale("en_US"),
     heartbeat(0),
@@ -40,7 +40,8 @@ ConnectionSettings::ConnectionSettings()
     tcpNoDelay(false),
     service(qpid::saslName),
     minSsf(0),
-    maxSsf(256)
+    maxSsf(256),
+    sslCertName("")
 {}
 
 ConnectionSettings::~ConnectionSettings() {}

Modified: qpid/trunk/qpid/cpp/src/qpid/client/SslConnector.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/client/SslConnector.cpp?rev=1066508&r1=1066507&r2=1066508&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/client/SslConnector.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/client/SslConnector.cpp Wed Feb  2 16:00:51 2011
@@ -7,9 +7,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *   http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -130,7 +130,7 @@ class SslConnector : public Connector
 
 public:
     SslConnector(Poller::shared_ptr p, framing::ProtocolVersion pVersion,
-              const ConnectionSettings&, 
+              const ConnectionSettings&,
               ConnectionImpl*);
 };
 
@@ -170,7 +170,7 @@ SslConnector::SslConnector(Poller::share
                      const ConnectionSettings& settings,
                      ConnectionImpl* cimpl)
     : maxFrameSize(settings.maxFrameSize),
-      version(ver), 
+      version(ver),
       initiated(false),
       closed(true),
       shutdownHandler(0),
@@ -179,8 +179,11 @@ SslConnector::SslConnector(Poller::share
       poller(p)
 {
     QPID_LOG(debug, "SslConnector created for " << version.toString());
-    //TODO: how do we want to handle socket configuration with ssl?
-    //settings.configureSocket(socket);
+
+    if (settings.sslCertName != "") {
+        QPID_LOG(debug, "ssl-cert-name = " << settings.sslCertName);
+        socket.setCertName(settings.sslCertName);
+    }
 }
 
 SslConnector::~SslConnector() {
@@ -244,14 +247,14 @@ void SslConnector::setShutdownHandler(Sh
 }
 
 OutputHandler* SslConnector::getOutputHandler() {
-    return this; 
+    return this;
 }
 
 sys::ShutdownHandler* SslConnector::getShutdownHandler() const {
     return shutdownHandler;
 }
 
-const std::string& SslConnector::getIdentifier() const { 
+const std::string& SslConnector::getIdentifier() const {
     return identifier;
 }
 
@@ -271,7 +274,7 @@ void SslConnector::Writer::init(std::str
     aio = a;
     newBuffer();
 }
-void SslConnector::Writer::handle(framing::AMQFrame& frame) { 
+void SslConnector::Writer::handle(framing::AMQFrame& frame) {
     Mutex::ScopedLock l(lock);
     frames.push_back(frame);
     if (frame.getEof() || (bounds && bounds->getCurrentSize() >= maxFrameSize)) {
@@ -372,7 +375,7 @@ const SecuritySettings* SslConnector::ge
 {
     securitySettings.ssf = socket.getKeyLen();
     securitySettings.authid = "dummy";//set to non-empty string to enable external authentication
-    return &securitySettings; 
+    return &securitySettings;
 }
 
 }} // namespace qpid::client

Modified: qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp?rev=1066508&r1=1066507&r2=1066508&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp Wed Feb  2 16:00:51 2011
@@ -7,9 +7,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *   http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -42,7 +42,7 @@ using qpid::framing::Uuid;
 void convert(const Variant::List& from, std::vector<std::string>& to)
 {
     for (Variant::List::const_iterator i = from.begin(); i != from.end(); ++i) {
-        to.push_back(i->asString());                
+        to.push_back(i->asString());
     }
 }
 
@@ -108,9 +108,11 @@ void convert(const Variant::Map& from, C
     setIfFound(from, "bounds", to.bounds);
 
     setIfFound(from, "transport", to.protocol);
+
+    setIfFound(from, "ssl-cert-name", to.sslCertName);
 }
 
-ConnectionImpl::ConnectionImpl(const std::string& url, const Variant::Map& options) : 
+ConnectionImpl::ConnectionImpl(const std::string& url, const Variant::Map& options) :
     reconnect(false), timeout(-1), limit(-1),
     minReconnectInterval(3), maxReconnectInterval(60),
     retries(0), reconnectOnLimitExceeded(true)
@@ -135,7 +137,7 @@ void ConnectionImpl::setOptions(const Va
         setIfFound(options, "reconnect-interval-max", maxReconnectInterval);
     }
     setIfFound(options, "reconnect-urls", urls);
-    setIfFound(options, "x-reconnect-on-limit-exceeded", reconnectOnLimitExceeded);    
+    setIfFound(options, "x-reconnect-on-limit-exceeded", reconnectOnLimitExceeded);
 }
 
 void ConnectionImpl::setOption(const std::string& name, const Variant& value)
@@ -216,7 +218,7 @@ qpid::messaging::Session ConnectionImpl:
         } catch (const qpid::SessionException& e) {
             throw qpid::messaging::SessionError(e.what());
         } catch (const std::exception& e) {
-            throw qpid::messaging::MessagingException(e.what());            
+            throw qpid::messaging::MessagingException(e.what());
         }
     }
     return impl;

Modified: qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h?rev=1066508&r1=1066507&r2=1066508&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h Wed Feb  2 16:00:51 2011
@@ -10,9 +10,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *   http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

Modified: qpid/trunk/qpid/cpp/src/qpid/sys/ssl/SslSocket.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/ssl/SslSocket.cpp?rev=1066508&r1=1066507&r2=1066508&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/sys/ssl/SslSocket.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/sys/ssl/SslSocket.cpp Wed Feb  2 16:00:51 2011
@@ -7,9 +7,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *   http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -52,9 +52,9 @@ namespace ssl {
 namespace {
 std::string getName(int fd, bool local, bool includeService = false)
 {
-    ::sockaddr_storage name; // big enough for any socket address    
+    ::sockaddr_storage name; // big enough for any socket address
     ::socklen_t namelen = sizeof(name);
-    
+
     int result = -1;
     if (local) {
         result = ::getsockname(fd, (::sockaddr*)&name, &namelen);
@@ -67,8 +67,8 @@ std::string getName(int fd, bool local, 
     char servName[NI_MAXSERV];
     char dispName[NI_MAXHOST];
     if (includeService) {
-        if (int rc=::getnameinfo((::sockaddr*)&name, namelen, dispName, sizeof(dispName), 
-                                 servName, sizeof(servName), 
+        if (int rc=::getnameinfo((::sockaddr*)&name, namelen, dispName, sizeof(dispName),
+                                 servName, sizeof(servName),
                                  NI_NUMERICHOST | NI_NUMERICSERV) != 0)
             throw QPID_POSIX_ERROR(rc);
         return std::string(dispName) + ":" + std::string(servName);
@@ -82,9 +82,9 @@ std::string getName(int fd, bool local, 
 
 std::string getService(int fd, bool local)
 {
-    ::sockaddr_storage name; // big enough for any socket address    
+    ::sockaddr_storage name; // big enough for any socket address
     ::socklen_t namelen = sizeof(name);
-    
+
     int result = -1;
     if (local) {
         result = ::getsockname(fd, (::sockaddr*)&name, &namelen);
@@ -95,8 +95,8 @@ std::string getService(int fd, bool loca
     QPID_POSIX_CHECK(result);
 
     char servName[NI_MAXSERV];
-    if (int rc=::getnameinfo((::sockaddr*)&name, namelen, 0, 0, 
-                                 servName, sizeof(servName), 
+    if (int rc=::getnameinfo((::sockaddr*)&name, namelen, 0, 0,
+                                 servName, sizeof(servName),
                                  NI_NUMERICHOST | NI_NUMERICSERV) != 0)
         throw QPID_POSIX_ERROR(rc);
     return servName;
@@ -132,8 +132,8 @@ std::string getDomainFromSubject(std::st
 
 }
 
-SslSocket::SslSocket() : IOHandle(new IOHandlePrivate()), socket(0), prototype(0) 
-{ 
+SslSocket::SslSocket() : IOHandle(new IOHandlePrivate()), socket(0), prototype(0)
+{
     impl->fd = ::socket (PF_INET, SOCK_STREAM, 0);
     if (impl->fd < 0) throw QPID_POSIX_ERROR(errno);
     socket = SSL_ImportFD(0, PR_ImportTCPSocket(impl->fd));
@@ -145,12 +145,12 @@ SslSocket::SslSocket() : IOHandle(new IO
  * PR_Accept, we have to reset the handshake.
  */
 SslSocket::SslSocket(IOHandlePrivate* ioph, PRFileDesc* model) : IOHandle(ioph), socket(0), prototype(0)
-{ 
+{
     socket = SSL_ImportFD(model, PR_ImportTCPSocket(impl->fd));
     NSS_CHECK(SSL_ResetHandshake(socket, true));
 }
 
-void SslSocket::setNonblocking() const 
+void SslSocket::setNonblocking() const
 {
     PRSocketOptionData option;
     option.option = PR_SockOpt_Nonblocking;
@@ -164,7 +164,15 @@ void SslSocket::connect(const std::strin
     namestream << host << ":" << port;
     connectname = namestream.str();
 
-    void* arg = SslOptions::global.certName.empty() ? 0 : const_cast<char*>(SslOptions::global.certName.c_str());
+    void* arg;
+    // Use the connection's cert-name if it has one; else use global cert-name
+    if (certname != "") {
+        arg = const_cast<char*>(certname.c_str());
+    } else if (SslOptions::global.certName.empty()) {
+        arg = 0;
+    } else {
+        arg = const_cast<char*>(SslOptions::global.certName.c_str());
+    }
     NSS_CHECK(SSL_GetClientAuthDataHook(socket, NSS_GetClientAuthData, arg));
     NSS_CHECK(SSL_SetURL(socket, host.data()));
 
@@ -220,7 +228,7 @@ int SslSocket::listen(uint16_t port, int
         throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(errno)));
     if (::listen(socket, backlog) < 0)
         throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(errno)));
-    
+
     socklen_t namelen = sizeof(name);
     if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0)
         throw QPID_POSIX_ERROR(errno);
@@ -235,7 +243,7 @@ SslSocket* SslSocket::accept() const
         return new SslSocket(new IOHandlePrivate(afd), prototype);
     } else if (errno == EAGAIN) {
         return 0;
-    } else { 
+    } else {
         throw QPID_POSIX_ERROR(errno);
     }
 }
@@ -303,6 +311,11 @@ void SslSocket::setTcpNoDelay(bool nodel
     }
 }
 
+void SslSocket::setCertName(const std::string& name)
+{
+    certname = name;
+}
+
 
 /** get the bit length of the current cipher's key */
 int SslSocket::getKeyLen() const

Modified: qpid/trunk/qpid/cpp/src/qpid/sys/ssl/SslSocket.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/ssl/SslSocket.h?rev=1066508&r1=1066507&r2=1066508&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/sys/ssl/SslSocket.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/sys/ssl/SslSocket.h Wed Feb  2 16:00:51 2011
@@ -10,9 +10,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *   http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -41,13 +41,18 @@ class SslSocket : public qpid::sys::IOHa
 public:
     /** Create a socket wrapper for descriptor. */
     SslSocket();
-    
+
     /** Set socket non blocking */
     void setNonblocking() const;
 
     /** Set tcp-nodelay */
     void setTcpNoDelay(bool nodelay) const;
 
+    /** Set SSL cert-name. Allows the cert-name to be set per
+     * connection, overriding global cert-name settings from
+     * NSSInit().*/
+    void setCertName(const std::string& certName);
+
     void connect(const std::string& host, uint16_t port) const;
 
     void close() const;
@@ -59,33 +64,33 @@ public:
      *@return The bound port.
      */
     int listen(uint16_t port = 0, int backlog = 10, const std::string& certName = "localhost.localdomain", bool clientAuth = false) const;
-    
-    /** 
+
+    /**
      * Accept a connection from a socket that is already listening
      * and has an incoming connection
      */
     SslSocket* accept() const;
 
-    // TODO The following are raw operations, maybe they need better wrapping? 
+    // TODO The following are raw operations, maybe they need better wrapping?
     int read(void *buf, size_t count) const;
     int write(const void *buf, size_t count) const;
 
-    /** Returns the "socket name" ie the address bound to 
+    /** Returns the "socket name" ie the address bound to
      * the near end of the socket
      */
     std::string getSockname() const;
 
-    /** Returns the "peer name" ie the address bound to 
+    /** Returns the "peer name" ie the address bound to
      * the remote end of the socket
      */
     std::string getPeername() const;
 
-    /** 
+    /**
      * Returns an address (host and port) for the remote end of the
      * socket
      */
     std::string getPeerAddress() const;
-    /** 
+    /**
      * Returns an address (host and port) for the local end of the
      * socket
      */
@@ -111,6 +116,8 @@ public:
 private:
     mutable std::string connectname;
     mutable PRFileDesc* socket;
+    std::string certname;
+
     /**
      * 'model' socket, with configuration to use when importing
      * accepted sockets for use as ssl sockets. Set on listen(), used

Modified: qpid/trunk/qpid/cpp/src/tests/ssl_test
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/ssl_test?rev=1066508&r1=1066507&r2=1066508&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/ssl_test (original)
+++ qpid/trunk/qpid/cpp/src/tests/ssl_test Wed Feb  2 16:00:51 2011
@@ -8,9 +8,9 @@
 # to you under the Apache License, Version 2.0 (the
 # "License"); you may not use this file except in compliance
 # with the License.  You may obtain a copy of the License at
-# 
+#
 #   http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing,
 # software distributed under the License is distributed on an
 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -26,6 +26,7 @@ CONFIG=$(dirname $0)/config.null
 CERT_DIR=`pwd`/test_cert_db
 CERT_PW_FILE=`pwd`/cert.password
 TEST_HOSTNAME=127.0.0.1
+TEST_CLIENT_CERT=rumplestiltskin
 COUNT=10
 
 trap cleanup EXIT
@@ -36,7 +37,8 @@ create_certs() {
     #create certificate and key databases with single, simple, self-signed certificate in it
     mkdir ${CERT_DIR}
     certutil -N -d ${CERT_DIR} -f ${CERT_PW_FILE}
-    certutil -S -d ${CERT_DIR} -n ${TEST_HOSTNAME} -s "CN=${TEST_HOSTNAME}" -t "CT,," -x -f ${CERT_PW_FILE} -z /usr/bin/certutil 
+    certutil -S -d ${CERT_DIR} -n ${TEST_HOSTNAME} -s "CN=${TEST_HOSTNAME}" -t "CT,," -x -f ${CERT_PW_FILE} -z /usr/bin/certutil
+    certutil -S -d ${CERT_DIR} -n ${TEST_CLIENT_CERT} -s "CN=${TEST_CLIENT_CERT}" -t "CT,," -x -f ${CERT_PW_FILE} -z /usr/bin/certutil
 }
 
 delete_certs() {
@@ -46,11 +48,19 @@ delete_certs() {
 }
 
 COMMON_OPTS="--daemon --no-data-dir --no-module-dir --auth no --config $CONFIG --load-module $SSL_LIB --ssl-cert-db $CERT_DIR --ssl-cert-password-file $CERT_PW_FILE --ssl-cert-name $TEST_HOSTNAME --require-encryption"
-start_broker() { ../qpidd --transport ssl --port 0 --ssl-port 0 $COMMON_OPTS; }
+start_broker() { # $1 = extra opts
+    ../qpidd --transport ssl --port 0 --ssl-port 0 $COMMON_OPTS $1;
+}
 
-cleanup() {
+stop_brokers() {
     test -n "$PORT" && ../qpidd --no-module-dir -qp $PORT
     test -n "$PORT2" && ../qpidd --no-module-dir -qp $PORT2
+    PORT=""
+    PORT2=""
+}
+
+cleanup() {
+    stop_brokers
     delete_certs
 }
 
@@ -76,11 +86,29 @@ export QPID_SSL_CERT_PASSWORD_FILE=${CER
 ./qpid-perftest --count ${COUNT} --port ${PORT} -P ssl -b $TEST_HOSTNAME --summary
 
 ## Test connection with a URL
-URL=amqp:ssl:$TEST_HOSTNAME:$PORT 
+URL=amqp:ssl:$TEST_HOSTNAME:$PORT
 ./qpid-send -b $URL --content-string=hello -a "foo;{create:always}"
 MSG=`./qpid-receive -b $URL -a "foo;{create:always}" --messages 1`
 test "$MSG" = "hello" || { echo "receive failed '$MSG' != 'hello'"; exit 1; }
 
+#### Client Authentication tests
+
+PORT2=`start_broker --ssl-require-client-authentication`  || error "Could not start broker"
+echo "Running SSL client authentication test on port $PORT2"
+URL=amqp:ssl:$TEST_HOSTNAME:$PORT2
+
+## See if you can set the SSL cert-name for the connection
+./qpid-send -b $URL --connection-options "{ssl-cert-name: $TEST_CLIENT_CERT }"  --content-string=hello -a "bar;{create:always}"
+MSG2=`./qpid-receive -b $URL  --connection-options "{ssl-cert-name: $TEST_CLIENT_CERT }" -a "bar;{create:always}" --messages 1`
+test "$MSG2" = "hello" || { echo "receive failed '$MSG2' != 'hello'"; exit 1; }
+
+## Make sure that connect fails with an invalid SSL cert-name
+./qpid-send -b $URL --connection-options "{ssl-cert-name: pignose }" --content-string=hello -a "baz;{create:always}" 2>/dev/null 1>/dev/null
+MSG3=`./qpid-receive -b $URL  --connection-options "{ssl-cert-name: pignose }" -a "baz;{create:always}" --messages 1 2>/dev/null`
+test "$MSG3" = "" || { echo "receive succeeded without valid ssl cert '$MSG3' != ''"; exit 1; }
+
+stop_brokers
+
 test -z $CLUSTER_LIB && exit 0	# Exit if cluster not supported.
 
 ## Test failover in a cluster using SSL only



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org