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

qpid-proton git commit: PROTON-1052: SSL support for C++ binding

Repository: qpid-proton
Updated Branches:
  refs/heads/master a267629f9 -> cf784e2a0


PROTON-1052: SSL support for C++ binding


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/cf784e2a
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/cf784e2a
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/cf784e2a

Branch: refs/heads/master
Commit: cf784e2a04b56a91b13ed7346931721868aa263f
Parents: a267629
Author: Clifford Jansen <cl...@apache.org>
Authored: Sun Nov 29 23:11:11 2015 -0800
Committer: Clifford Jansen <cl...@apache.org>
Committed: Mon Nov 30 08:02:29 2015 -0800

----------------------------------------------------------------------
 examples/cpp/CMakeLists.txt                     |   1 +
 examples/cpp/broker.hpp                         |   2 +-
 examples/cpp/connection_options.cpp             |   2 +-
 examples/cpp/ssl.cpp                            | 165 +++++++++++++++++++
 examples/cpp/ssl_certs/README.txt               |  24 +++
 examples/cpp/ssl_certs/tclient-certificate.p12  | Bin 0 -> 1032 bytes
 examples/cpp/ssl_certs/tclient-certificate.pem  |  19 +++
 examples/cpp/ssl_certs/tclient-full.p12         | Bin 0 -> 2476 bytes
 examples/cpp/ssl_certs/tclient-private-key.pem  |  30 ++++
 examples/cpp/ssl_certs/tserver-certificate.p12  | Bin 0 -> 1032 bytes
 examples/cpp/ssl_certs/tserver-certificate.pem  |  19 +++
 examples/cpp/ssl_certs/tserver-full.p12         | Bin 0 -> 2476 bytes
 examples/cpp/ssl_certs/tserver-private-key.pem  |  30 ++++
 proton-c/bindings/cpp/CMakeLists.txt            |   2 +
 .../bindings/cpp/include/proton/acceptor.hpp    |   3 +
 .../cpp/include/proton/connection_options.hpp   |   6 +-
 .../bindings/cpp/include/proton/reactor.hpp     |   2 +
 proton-c/bindings/cpp/include/proton/ssl.hpp    | 127 ++++++++++++++
 .../bindings/cpp/include/proton/transport.hpp   |   1 +
 .../bindings/cpp/src/connection_options.cpp     |  33 +++-
 proton-c/bindings/cpp/src/container_impl.cpp    |  17 +-
 proton-c/bindings/cpp/src/engine.cpp            |   2 +-
 proton-c/bindings/cpp/src/ssl.cpp               |  75 +++++++++
 proton-c/bindings/cpp/src/ssl_domain.cpp        | 113 +++++++++++++
 proton-c/bindings/cpp/src/transport.cpp         |   5 +
 25 files changed, 663 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt
index 8890e2d..3858df3 100644
--- a/examples/cpp/CMakeLists.txt
+++ b/examples/cpp/CMakeLists.txt
@@ -36,6 +36,7 @@ set(examples
   server_direct
   recurring_timer
   connection_options
+  ssl
   encode_decode)
 
 if (NOT WIN32)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/broker.hpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.hpp b/examples/cpp/broker.hpp
index 32fd5c7..2d94b5a 100644
--- a/examples/cpp/broker.hpp
+++ b/examples/cpp/broker.hpp
@@ -162,7 +162,7 @@ class broker_handler : public proton::messaging_handler {
 
     void on_link_closing(proton::event &e) {
         proton::link lnk = e.link();
-        if (!!lnk.sender()) 
+        if (!!lnk.sender())
             unsubscribe(lnk.sender());
     }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/connection_options.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/connection_options.cpp b/examples/cpp/connection_options.cpp
index da3c4d9..ab21f76 100644
--- a/examples/cpp/connection_options.cpp
+++ b/examples/cpp/connection_options.cpp
@@ -47,7 +47,7 @@ class main_handler : public proton::messaging_handler {
 
     void on_start(proton::event &e) {
         // Connection options for this connection.  Merged with and overriding the container's
-        // client_connection_options() settings. 
+        // client_connection_options() settings.
         e.container().connect(url, connection_options().handler(&conn_handler).max_frame_size(2468));
     }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/ssl.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl.cpp b/examples/cpp/ssl.cpp
new file mode 100644
index 0000000..f81eb62
--- /dev/null
+++ b/examples/cpp/ssl.cpp
@@ -0,0 +1,165 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * 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
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "proton/acceptor.hpp"
+#include "proton/container.hpp"
+#include "proton/messaging_handler.hpp"
+#include "proton/connection_options.hpp"
+#include "proton/transport.hpp"
+#include "proton/ssl.hpp"
+
+#include <iostream>
+
+using proton::connection_options;
+using proton::client_domain;
+using proton::server_domain;
+using proton::ssl_certificate;
+
+// Helper functions defined below.
+bool using_OpenSSL();
+std::string platform_CA(const std::string &base_name);
+ssl_certificate platform_certificate(const std::string &base_name, const std::string &passwd);
+std::string cert_directory;
+
+
+struct server_handler : public proton::messaging_handler {
+    proton::acceptor acceptor;
+
+    void on_connection_opened(proton::event &e) {
+        std::cout << "Inbound server connection connected via SSL.  Protocol: " <<
+            e.connection().transport().ssl().protocol() << std::endl;
+        acceptor.close();
+    }
+
+    void on_message(proton::event &e) {
+        std::cout << e.message().body() << std::endl;
+    }
+};
+
+
+class hello_world_direct : public proton::messaging_handler {
+  private:
+    proton::url url;
+    server_handler s_handler;
+
+  public:
+    hello_world_direct(const proton::url& u) : url(u) {}
+
+    void on_start(proton::event &e) {
+        // Configure listener.  Details vary by platform.
+        ssl_certificate server_cert = platform_certificate("tserver", "tserverpw");
+        server_domain sdomain(server_cert);
+        connection_options server_opts;
+        server_opts.server_domain(sdomain).handler(&s_handler);
+        e.container().server_connection_options(server_opts);
+
+        // Configure client with a Certificate Authority database populated with the server's self signed certificate.
+        connection_options client_opts;
+        client_opts.client_domain(platform_CA("tserver"));
+        // Validate the server certificate against the known name in the certificate.
+        client_opts.peer_hostname("test_server");
+#ifdef PN_COMING_SOON
+        // Turn off unnecessary SASL processing.
+        client_opts.sasl_enabled(false);
+#endif
+        e.container().client_connection_options(client_opts);
+
+        s_handler.acceptor = e.container().listen(url);
+        e.container().open_sender(url);
+    }
+
+    void on_connection_opened(proton::event &e) {
+        std::cout << "Outgoing client connection connected via SSL.  Server certificate has subject " <<
+            e.connection().transport().ssl().remote_subject() << std::endl;
+    }
+
+    void on_sendable(proton::event &e) {
+        proton::message m;
+        m.body("Hello World!");
+        e.sender().send(m);
+        e.sender().close();
+    }
+
+    void on_accepted(proton::event &e) {
+        // All done.
+        e.connection().close();
+    }
+};
+
+int main(int argc, char **argv) {
+    try {
+        // Pick an "unusual" port since we are going to be talking to ourselves, not a broker.
+        // Note the use of "amqps" as the URL scheme to denote a TLS/SSL connection.
+        std::string url = argc > 1 ? argv[1] : "amqps://127.0.0.1:8888/examples";
+        // Location of certificates and private key information:
+        if (argc > 2) {
+            cert_directory = argv[2];
+            size_t sz = cert_directory.size();
+            if (sz && cert_directory[sz -1] != '/')
+                cert_directory.append("/");
+        }
+        else cert_directory = "ssl_certs/";
+
+        hello_world_direct hwd(url);
+        proton::container(hwd).run();
+        return 0;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+    return 1;
+}
+
+
+bool using_OpenSSL() {
+    // Current defaults.
+#if defined(WIN32)
+    return false;
+#else
+    return true;
+#endif
+}
+
+ssl_certificate platform_certificate(const std::string &base_name, const std::string &passwd) {
+    if (using_OpenSSL()) {
+        // The first argument will be the name of the file containing the public certificate, the
+        // second argument will be the name of the file containing the private key.
+        return ssl_certificate(cert_directory + base_name + "-certificate.pem",
+                               cert_directory + base_name + "-private-key.pem", passwd);
+    }
+    else {
+        // Windows SChannel
+        // The first argument will be the database or store that contains one or more complete certificates
+        // (public and private data).  The second will be an optional name of the certificate in the store
+        // (not used in this example with one certificate per store).
+        return ssl_certificate(cert_directory + base_name + "-full.p12", "", passwd);
+    }
+}
+
+std::string platform_CA(const std::string &base_name) {
+    if (using_OpenSSL()) {
+        // In this simple example with self-signed certificates, the peer's certificate is the CA database.
+        return cert_directory + base_name + "-certificate.pem";
+    }
+    else {
+        // Windows SChannel.  Use a pkcs#12 file with just the peer's public certificate information.
+        return cert_directory + base_name + "-certificate.p12";
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/ssl_certs/README.txt
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_certs/README.txt b/examples/cpp/ssl_certs/README.txt
new file mode 100644
index 0000000..9a8a4f9
--- /dev/null
+++ b/examples/cpp/ssl_certs/README.txt
@@ -0,0 +1,24 @@
+This directory contains basic self signed test certificates for use by
+proton examples.
+
+The ".pem" files are in the format expected by proton implementations
+using OpenSSL.  The ".p12" file are for Windows implementations using
+SChannel.
+
+The commands used to generate the certificates follow.
+
+
+make_pn_cert()
+{
+  name=$1
+  subject=$2
+  passwd=$3
+  # create the pem files
+  openssl req -newkey rsa:2048 -keyout $name-private-key.pem -out $name-certificate.pem -subj $subject -passout pass:$passwd -x509 -days 3650
+  # create the p12 files
+  openssl pkcs12 -export -out $name-full.p12 -passin pass:$passwd -passout pass:$passwd -inkey $name-private-key.pem -in $name-certificate.pem -name $name
+  openssl pkcs12 -export -out $name-certificate.p12 -in $name-certificate.pem -name $name -nokeys -passout pass:
+}
+
+make_pn_cert tserver /CN=test_server/OU=proton_test tserverpw
+make_pn_cert tclient /CN=test_client/OU=proton_test tclientpw

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/ssl_certs/tclient-certificate.p12
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_certs/tclient-certificate.p12 b/examples/cpp/ssl_certs/tclient-certificate.p12
new file mode 100644
index 0000000..4d0e000
Binary files /dev/null and b/examples/cpp/ssl_certs/tclient-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/ssl_certs/tclient-certificate.pem
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_certs/tclient-certificate.pem b/examples/cpp/ssl_certs/tclient-certificate.pem
new file mode 100644
index 0000000..8088e2e
--- /dev/null
+++ b/examples/cpp/ssl_certs/tclient-certificate.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDKzCCAhOgAwIBAgIJAIV7frIjftgcMA0GCSqGSIb3DQEBCwUAMCwxFDASBgNV
+BAMMC3Rlc3RfY2xpZW50MRQwEgYDVQQLDAtwcm90b25fdGVzdDAeFw0xNTExMjcx
+ODEwMzlaFw0yNTExMjQxODEwMzlaMCwxFDASBgNVBAMMC3Rlc3RfY2xpZW50MRQw
+EgYDVQQLDAtwcm90b25fdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAPCIS4qUdOtQplUxZ6WW0LXcvosqFP6qOiCARLSEWpR3B8bq213rzefwwfcM
+4TtMr88bP+huLKmlyMfwpl8yB88eXkscPgaAce2zk24urWkFXKSQ6GPitWBLGqBa
+V+W0wJ4mfW7MwefVslWfGXI381QEUlBHjkFG30AtzMMTRj2GK2JqUlRXZPljGyB7
+WcXwxcoS+HkKV7FtHWSkLAzyXwQ9vsCUEYdWTUaGXfCUNRSRV7h1LIANbu03NxV0
+XdEl7WXcr7tuTw3axeUGhRFVhLegrxKLuZTTno4aAJnEr8uaDzjxvXnv3Ne2igvy
+gRfZgOMx+XrZEob9OpAoRghQt4cCAwEAAaNQME4wHQYDVR0OBBYEFE4vbyiM0RjG
+TLMLLGGhMZE/5x1GMB8GA1UdIwQYMBaAFE4vbyiM0RjGTLMLLGGhMZE/5x1GMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAErr/rvLS9Ig0UCMwh1J1lA9
+/gvXf93iIK/SjrFIAqYRmfZxg4husfoes8t2hFUeuqoH05TuSOoXG8p8DpgTSGmF
+jAFe+T90vJZTm0oqZkkkI/hdzjGQoHURRp9/O2Z/lm39KSKGVAN5pUWCUDi/G5iS
+P9LZPJN6a5syXMrR6x62IPxAXowlpXkRghKClF3zPOaOBTzT1V27EkI8IEgC+p45
+246EooLnw8ibB+ucNc3KHNzpgKGVd/622+I+Q5eg9AT9PLFttP+R2ECsrVDDPYuA
+p0qaSnwgeozj/d6K3FOgKKEKbzBmpWgkv0jdcVk18aPMHypI/RDtZ/+3ET2Ksi8=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/ssl_certs/tclient-full.p12
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_certs/tclient-full.p12 b/examples/cpp/ssl_certs/tclient-full.p12
new file mode 100644
index 0000000..ad2d7d3
Binary files /dev/null and b/examples/cpp/ssl_certs/tclient-full.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/ssl_certs/tclient-private-key.pem
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_certs/tclient-private-key.pem b/examples/cpp/ssl_certs/tclient-private-key.pem
new file mode 100644
index 0000000..e5c114d
--- /dev/null
+++ b/examples/cpp/ssl_certs/tclient-private-key.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQICy6ghWp45z4CAggA
+MBQGCCqGSIb3DQMHBAiVdDoo4NIghQSCBMixGm1bm/omMxsaKnIPO7zm5dyLexJ+
+yTFpmh2KV7kQqmpzCyIOdoG6K8YqFnie2XdFWm3S8faRHoMq54bDmyEWIxfQPq5f
+I1iYFbIZkbnhUvK53RActsEUMf0locS4xylU7VQK3XTAwp0TVip3Lp3ehEMEdcXL
+iUWibGsoTPKcY9MIWGXZAJXsEXoeHt6k2hHo1G4E0/Bi6mLW1LY/cxZCjHTGD6qI
+Kt54SCCDvinqVa+rixw6yX9F14EA6bhALami8e+Ccd3lqHOyYlXcBaSS1ezCg6ig
+oNK97mC+gEGy1KlkZDKWXclFoOCBXRBe4DByre6Rlq3yeI9L42bvAuSBSmf5QT5g
+73Yl8vjEAKR65awBT09dPuKu7t+Fb6vkwF8/t+uyj9IuL+42UuXhMLK3ohf+6DbU
+8/zB4y3GXI80QmWM0+Wx4n6khFhPFLHt2q0Sn6V9PG1vtHyiq50oSCoyrPQLaecp
+hefnMCFBYTcT3JUwmoVGGy0boIAwL7T4aGsMt7QhwOx5tU35tKFxyY7m4fX14AKo
+2EIy+TPQwCGkGf3Puy/Pc9VA8IAxB5+WwSrjk+NeCv88eIX7gy43k4rCr+OmD9FF
+wknr3xoP3KYhNXjdZ4Ep/1UHSK+JAtzzbNLQjDcqN+gQPg/yUX6ih0j5K3Wvh9bK
+E/DvzbpJroUZPgzR+8z5O68CfsD+OIdpHBFTKqAFmzvUuqpADpr998LdCjD+lW+V
+xZZgZa8KEblwgiH3fdGbYl46Ho1zrZisf439DbqyybAuBIQB4NSZcL/MAgVGO17k
+QDpVElWZWYrFm4CFTcvS2HvIzRmbefF5m5oJedsN7Q6WQCp+3gnwYx1xIOknd7pW
+N4AHNnqjscSj9yACj/EiBVKAKNnC5H7ZGZTsaAjMETZyjLXfI2AZ3Fviz4zFR+oz
+NkAfFB6WUpRpl7H02FzrzYT7XkkLcXd6H6g+mv2iDa9uKWk/PS2QlqnJt8/dHEHD
+JKTG331yDK5GHlKAVGF3nP5BwFGgTQMuSoeiOervMXPUwDpQ8OaYkuaRej0cZLgT
+kAF9sUjqdsoYNcXDFHALp6y5g8qYkfrxrlIbKs82zIsmB5I+dtZbUaD3a0zAUrmW
+5Xm3Pc9dVP0EXKwfHz6zqPReEw2yYLisB5IoHd4M2wa3GzHBdra1ij4QTmvd3o7e
+buGFoX8KJQAcig0zpbYkoDP2gPhIh9rY4unVPQNX1Q8/wRsiJAZZsYvZY+A+SmuZ
+bwSwk+8ZJRsFzdYYYhQeRytD5cDAIQiClcI5Yj4T9dWQV/gf0N/wIBDNTMp0jJAy
+1l7PuXTfGZodNJWZH0oqsrNoWbn/k67NildvvofIKX+h09Nxszr670Pvj0qoHd5/
+CWq30lnxoJBUgbikFOz6ZuuHi/ZiCXL+haH+v8hJKN5ptRKnyYJQHchRB/IOGRoT
+5lmWxo8a7K+yXhp0VBDHJfw3685ms0xQX8Xj4X3MEuN64zd0fB1JmhtP12ydK85J
+ABawNKlRQPw5weckwtCviXQX+vX25S/xu3xA6IuqlHyqL/1t3DICzuxeOyT2mZxD
+tKQxEgNihPvu32vn9m74qA3adEaxuWPRkPZuTeITHOkMTZolvqYX/5olBsSgYwka
+7/g=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/ssl_certs/tserver-certificate.p12
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_certs/tserver-certificate.p12 b/examples/cpp/ssl_certs/tserver-certificate.p12
new file mode 100644
index 0000000..f38b67d
Binary files /dev/null and b/examples/cpp/ssl_certs/tserver-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/ssl_certs/tserver-certificate.pem
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_certs/tserver-certificate.pem b/examples/cpp/ssl_certs/tserver-certificate.pem
new file mode 100644
index 0000000..86231f3
--- /dev/null
+++ b/examples/cpp/ssl_certs/tserver-certificate.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDKzCCAhOgAwIBAgIJAPnYOOQCJ3kDMA0GCSqGSIb3DQEBCwUAMCwxFDASBgNV
+BAMMC3Rlc3Rfc2VydmVyMRQwEgYDVQQLDAtwcm90b25fdGVzdDAeFw0xNTExMjcx
+ODEwMzlaFw0yNTExMjQxODEwMzlaMCwxFDASBgNVBAMMC3Rlc3Rfc2VydmVyMRQw
+EgYDVQQLDAtwcm90b25fdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAKJNB78lgw4KtXDAvXocTLud6mbn6zgfB6ETIF+kcrukOH9DnPxjLBBM4Lig
+sp1+kmeudFK5/X8riDrvIW52b/rlEBLgLB+oDtI74m6OTbBs9L+FUFYOuxApetQF
+qoJy2vf9pWfy4uku24vCpeo7eVLi6ypu4lXE3LR+Km3FruHI1NKonHBMhwXSOWqF
+pYM6/4IZJ4fbV0+eU0Jrx+05s6XHg5vone2BVJKxeSIBje+zWnNnh8+qG0Z70Jgp
+aMetME5KGnLNgD1okpH0vb3lwjvuqkkx4WswGVZGbLLkSqqBpXPyM9fCFVy5aKSL
+DBq7IABQtO67O2nBzK3OyigHrUUCAwEAAaNQME4wHQYDVR0OBBYEFGV1PY0FCFbJ
+gpcDVKI6JGiRTt3kMB8GA1UdIwQYMBaAFGV1PY0FCFbJgpcDVKI6JGiRTt3kMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAIx1TOTGWnnbpan4bse7wuvH
+GYSNDJhoTVS+X1TC63xukJD1JBAsCNTqg/ZV6lN3XEl7vvOXfGoCiyXM6a9XOKUo
+gSDtMrIr+wTh6Ss1yRO8QcCJmxH5JDXNu1ojtwsjFW/vneI4IL9kwpDsSlMQEX/E
+EkkQwtAx/Cvfe7pecZL4qSeykJOUMTts9H8fCAZqEiRZBA3ugJxqF8jwLP3DoFVQ
+6QZzKDY6CSPqfMnVb5i0MAIYVDpau+e3N9dgQpZD22F/zbua0OVbfAPdiRMnYxML
+FT4sxLnh+5YVqwpVWbEKp4onHe2Fq6YIvAxUYAJ3SBA2C8O2RAVKWxf1jko3jYI=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/ssl_certs/tserver-full.p12
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_certs/tserver-full.p12 b/examples/cpp/ssl_certs/tserver-full.p12
new file mode 100644
index 0000000..d4a0e40
Binary files /dev/null and b/examples/cpp/ssl_certs/tserver-full.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/examples/cpp/ssl_certs/tserver-private-key.pem
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_certs/tserver-private-key.pem b/examples/cpp/ssl_certs/tserver-private-key.pem
new file mode 100644
index 0000000..91dcf0e
--- /dev/null
+++ b/examples/cpp/ssl_certs/tserver-private-key.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI1cT0c2J3GcQCAggA
+MBQGCCqGSIb3DQMHBAi1hxSX2LJ+EgSCBMheHJ0iXr5A36Natjk/LcAEeKUMT9s+
+sMzoQceCWe8qMlQluWksr9iDdZ4JRIE8cpK8dbmx4dLY/SShUzdlhJHCSa4zZBHq
+8cZ/jGUF/RF1rqdgjK589eUq+uOl3/gXKzG/SxBqayy6PSn12kX3qnvmlkXCmtwU
+lg+iBm5wRcJ0MyVHaJkyA8sW8gr186C/VAau6Yu0crQXN7NRo9snrd4ewuYMIEhZ
+hgaG9XsYQWB1bPhAaKj80CZGxsQbJyTwcbKKkB3IY4WXx8mmhuiNl+vKT3HBJ9Ju
+YB6tgIjs8CJ4X2P4aU3yNJwG1QldgHSqmFGQ19bcZAw3s3kzwjdzRf4H2V16XOBd
+zQ5AEs/ffVMzMIAfkb1gYwgunZ2CVwwDJ2mi1RcgkX+Og2aFQc+fxXcVOnDcGLxV
+6fuCuZ2lsXfoiIyRh9kj3L75N12GtVUvgBdnMuOc1wPw6XnGQtDwt0acJpdexLMG
+k0j57r/gcgzTcmF3qNM+y9L/HLssgrJkvVJw2Np5gmtIyfDocsDUWUbClS4dTpYf
+oTngUTU+vWtHBuaUnb+f5/WJaRS/S7mmR8usbVG3i9WnEr/vlPJpbJFSjW2S6u/H
+7cFxKUmmBZsSuEv/EKt9a+Sh62kprOChm4myqfCI1/gvNKfUZC6m0Vp8zf+2LgAq
+2RgbMuqysMjWUtV4kDRZT7oCYckUDwsCHdbLES3nmVrtBk2ShMKHBpDp8/GoRuiV
+jdV7/EjKM/M1kXtFYYe3z7Mxv++lKYIJ7bNwVrQ8nrhce/VwHw6D5emWXNCJXhKZ
+FW7EM2ZOZ9eaKOlCsIi8sbjV6Yie9IY6HJKKmi3CpO0Tv5kLBdHkru8vGCSFm3O1
+n7wz7Ys5FBSlZ19X0NwQSCQX1Q4w+tido6i1SCRX0qJEdTNGuGwVXMHCf4/1zyHV
+hj8vnxh8fzo79LFrwlTTgwLg1Mr8sEUFFDJ/raJ1AhFXi8n24trtNR8EHxRW8wtD
+CLCKaqkEqfBiFXK/Yq3RrefCayPHiD+DaNsI8BwefMGpED3vD8YYCjAzXNPh/CSF
+sc1i1jWMzbJhzOoFSPNXhlfusbUFMFQ/6olatmH47SY6HBBOL3DDP5uQ0jw8P454
+QBjlMOpEZmZxO6TcEtJwu0vzgog4rQ5g3NWy6SIpjWehNwTynLt7yM3R5WTI6cZs
+0GTv/rqo2/SUoNsFmnGIUwj/DrBe4XOAq1nS2ZlEctxKhBsKH0hMFp6D1rXOzrgl
+bwcq+oistoB0TLcThShyNgSqzW1znQ1n5SVUk9b5rRhSttJxn3yOMewH0i3v8bPo
+HOhP5kaGjblPsCYyhlL/SNVF0OXEGTwLNey7FQdWFOwVwTRRXe7k+uGZ2d5hg+Jn
+It/trDZ1RDYbVmB7/Qy73c16J4mvhOUJ2de5ZciFBjkidbiiUKLj9xnjK9k9Sauo
+MKhNnDMAEU5VDQM3xNe5BRdX8dFLwfF5H64sU3nROF83aUnDgvfFEowYPnCuPYfm
+m4aQHfoBSg4j3v1OeOwktcl+Q2TjxPHfWhbWeRBfxOTqQ/suYhnQChuFSK/qyo9K
+ccgotqghhunRsWMoZT25H7AZM6yKb1sMz/0oyMRIKeGqoYh+ULM5XLY0xNYd4/xU
+WtQ=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index 47ca937..6bc6445 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -64,6 +64,8 @@ set(qpid-proton-cpp-source
   src/request_response.cpp
   src/sender.cpp
   src/session.cpp
+  src/ssl.cpp
+  src/ssl_domain.cpp
   src/task.cpp
   src/terminus.cpp
   src/transport.cpp

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/include/proton/acceptor.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/acceptor.hpp b/proton-c/bindings/cpp/include/proton/acceptor.hpp
index cd77358..c5726aa 100644
--- a/proton-c/bindings/cpp/include/proton/acceptor.hpp
+++ b/proton-c/bindings/cpp/include/proton/acceptor.hpp
@@ -38,6 +38,9 @@ class acceptor : public object<pn_acceptor_t>
 
     /** close the acceptor */
     PN_CPP_EXTERN void close();
+#ifndef PROTON_1057_FIXED
+    friend class container_impl;
+#endif
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/include/proton/connection_options.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/connection_options.hpp b/proton-c/bindings/cpp/include/proton/connection_options.hpp
index 2755adf..c9701c9 100644
--- a/proton-c/bindings/cpp/include/proton/connection_options.hpp
+++ b/proton-c/bindings/cpp/include/proton/connection_options.hpp
@@ -63,7 +63,7 @@ class connection_options {
     PN_CPP_EXTERN void override(const connection_options& other);
 
     // TODO: Document options
-    
+
     PN_CPP_EXTERN connection_options& handler(class handler *);
     PN_CPP_EXTERN connection_options& max_frame_size(uint32_t max);
     PN_CPP_EXTERN connection_options& max_channels(uint16_t max);
@@ -71,11 +71,11 @@ class connection_options {
     PN_CPP_EXTERN connection_options& heartbeat(uint32_t t);
     PN_CPP_EXTERN connection_options& container_id(const std::string &id);
     PN_CPP_EXTERN connection_options& reconnect(const reconnect_timer &);
-#ifdef PN_CPP_SOON
     PN_CPP_EXTERN connection_options& client_domain(const class client_domain &);
     PN_CPP_EXTERN connection_options& server_domain(const class server_domain &);
     PN_CPP_EXTERN connection_options& peer_hostname(const std::string &name);
     PN_CPP_EXTERN connection_options& resume_id(const std::string &id);
+#ifdef PN_CPP_SOON
     PN_CPP_EXTERN connection_options& sasl_enabled(bool);
     PN_CPP_EXTERN connection_options& allow_insecure_mechs(bool);
     PN_CPP_EXTERN connection_options& allowed_mechs(const std::string &);
@@ -88,9 +88,9 @@ class connection_options {
     bool sasl_enabled() const;
     bool allow_insecure_mechs() const;
     std::string *allowed_mechs() const;
+#endif
     class client_domain &client_domain();
     class server_domain &server_domain();
-#endif
 
     class impl;
     pn_unique_ptr<impl> impl_;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/include/proton/reactor.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/reactor.hpp b/proton-c/bindings/cpp/include/proton/reactor.hpp
index 5f628ce..fa7d633 100644
--- a/proton-c/bindings/cpp/include/proton/reactor.hpp
+++ b/proton-c/bindings/cpp/include/proton/reactor.hpp
@@ -87,6 +87,8 @@ class reactor : public object<pn_reactor_t> {
     PN_CPP_EXTERN void yield();
 
     void container_context(container&);
+
+    friend class container_impl;
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/include/proton/ssl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/ssl.hpp b/proton-c/bindings/cpp/include/proton/ssl.hpp
new file mode 100644
index 0000000..d5d80d7
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/ssl.hpp
@@ -0,0 +1,127 @@
+#ifndef PROTON_CPP_SSL_H
+#define PROTON_CPP_SSL_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * 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
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "proton/export.hpp"
+#include "proton/pn_unique_ptr.hpp"
+#include "proton/counted.hpp"
+#include "proton/counted_ptr.hpp"
+
+#include "proton/ssl.h"
+
+#include <string>
+
+namespace proton {
+
+class connection_options;
+
+class ssl {
+  public:
+    enum verify_mode_t {
+        VERIFY_PEER = PN_SSL_VERIFY_PEER,
+        ANONYMOUS_PEER = PN_SSL_ANONYMOUS_PEER,
+        VERIFY_PEER_NAME = PN_SSL_VERIFY_PEER_NAME
+    };
+    /// Outcome specifier for an attempted session resume
+    enum resume_status_t {
+        UNKNOWN = PN_SSL_RESUME_UNKNOWN,    /**< Session resume state unknown/not supported */
+        NEW = PN_SSL_RESUME_NEW,            /**< Session renegotiated - not resumed */
+        REUSED = PN_SSL_RESUME_REUSED       /**< Session resumed from previous session. */
+    };
+    ssl(pn_ssl_t* s) : object_(s) {}
+    PN_CPP_EXTERN std::string cipher() const;
+    PN_CPP_EXTERN std::string protocol() const;
+    PN_CPP_EXTERN int ssf() const;
+    PN_CPP_EXTERN void peer_hostname(const std::string &);
+    PN_CPP_EXTERN std::string peer_hostname() const;
+    PN_CPP_EXTERN std::string remote_subject() const;
+    PN_CPP_EXTERN void resume_session_id(const std::string& session_id);
+    PN_CPP_EXTERN resume_status_t resume_status() const;
+
+private:
+    pn_ssl_t* object_;
+};
+
+
+class ssl_certificate {
+  public:
+    PN_CPP_EXTERN ssl_certificate(const std::string &certdb_main, const std::string &certdb_extra = std::string());
+    PN_CPP_EXTERN ssl_certificate(const std::string &certdb_main, const std::string &certdb_extra, const std::string &passwd);
+  private:
+    std::string certdb_main_;
+    std::string certdb_extra_;
+    std::string passwd_;
+    bool pw_set_;
+    friend class client_domain;
+    friend class server_domain;
+};
+
+class ssl_domain : public counted {
+    ssl_domain(bool server_type);
+    ~ssl_domain();
+  private:
+    pn_ssl_domain_t *impl_;
+    friend class client_domain;
+    friend class server_domain;
+};
+
+/** SSL/TLS configuration for inbound connections created from a listener */
+class server_domain {
+  public:
+    /** A server domain based on the supplied X509 certificate specifier. */
+    PN_CPP_EXTERN server_domain(ssl_certificate &cert);
+    /** A server domain requiring connecting clients to provide a client certificate. */
+    PN_CPP_EXTERN server_domain(ssl_certificate &cert, const std::string &trust_db,
+                                const std::string &advertise_db = std::string(),
+                                ssl::verify_mode_t mode = ssl::VERIFY_PEER);
+    /** A server domain restricted to available anonymous cipher suites on the platform. */
+    PN_CPP_EXTERN server_domain();
+  private:
+    pn_ssl_domain_t *pn_domain();
+    counted_ptr<ssl_domain> ssl_domain_;
+    server_domain(ssl_domain *);
+    friend class connection_options;
+    friend class container_impl;
+};
+
+
+/** SSL/TLS configuration for outgoing connections created */
+class client_domain {
+  public:
+    PN_CPP_EXTERN client_domain(const std::string &trust_db, ssl::verify_mode_t = ssl::VERIFY_PEER_NAME);
+    PN_CPP_EXTERN client_domain(ssl_certificate&, const std::string &trust_db, ssl::verify_mode_t = ssl::VERIFY_PEER_NAME);
+    /** A client domain restricted to available anonymous cipher suites on the platform. */
+    PN_CPP_EXTERN client_domain();
+  private:
+    pn_ssl_domain_t *pn_domain();
+    counted_ptr<ssl_domain> ssl_domain_;
+    client_domain(ssl_domain *);
+    friend class connection_options;
+    friend class container_impl;
+};
+
+
+
+
+}
+
+#endif  /*!PROTON_CPP_SSL_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/include/proton/transport.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/transport.hpp b/proton-c/bindings/cpp/include/proton/transport.hpp
index 0b73a8c..3f664bc 100644
--- a/proton-c/bindings/cpp/include/proton/transport.hpp
+++ b/proton-c/bindings/cpp/include/proton/transport.hpp
@@ -47,6 +47,7 @@ class transport : public object<pn_transport_t>
     PN_CPP_EXTERN uint16_t remote_max_channels() const;
     PN_CPP_EXTERN uint32_t idle_timeout() const;
     PN_CPP_EXTERN uint32_t remote_idle_timeout() const;
+    PN_CPP_EXTERN class ssl ssl() const;
     friend class connection_options;
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/src/connection_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection_options.cpp b/proton-c/bindings/cpp/src/connection_options.cpp
index 6d5b829..5097e42 100644
--- a/proton-c/bindings/cpp/src/connection_options.cpp
+++ b/proton-c/bindings/cpp/src/connection_options.cpp
@@ -21,6 +21,7 @@
 #include "proton/connection_options.hpp"
 #include "proton/reconnect_timer.hpp"
 #include "proton/transport.hpp"
+#include "proton/ssl.hpp"
 #include "contexts.hpp"
 #include "connector.hpp"
 #include "msg.hpp"
@@ -47,11 +48,11 @@ class connection_options::impl {
     option<uint32_t> heartbeat;
     option<std::string> container_id;
     option<reconnect_timer> reconnect;
-#ifdef PN_CCP_SOON
     option<class client_domain> client_domain;
     option<class server_domain> server_domain;
     option<std::string> peer_hostname;
     option<std::string> resume_id;
+#ifdef PN_CCP_SOON
     option<bool> sasl_enabled;
     option<std::string> allowed_mechs;
     option<bool> allow_insecure_mechs;
@@ -68,6 +69,26 @@ class connection_options::impl {
         // transport not yet configured.
         if (pnt && (uninit || (outbound && !outbound->transport_configured())))
         {
+            if (outbound && outbound->address().scheme() == url::AMQPS) {
+                // Configure outbound ssl options. pni_acceptor_readable handles the inbound case.
+                const char* id = resume_id.value.empty() ? NULL : resume_id.value.c_str();
+                pn_ssl_t *ssl = pn_ssl(pnt);
+                if (pn_ssl_init(ssl, client_domain.value.pn_domain(), id))
+                    throw error(MSG("client SSL/TLS initialization error"));
+                if (peer_hostname.set && !peer_hostname.value.empty())
+                    if (pn_ssl_set_peer_hostname(ssl, peer_hostname.value.c_str()))
+                        throw error(MSG("error in SSL/TLS peer hostname \"") << peer_hostname.value << '"');
+#ifdef PROTON_1054_FIXED
+            } else if (!outbound) {
+                pn_acceptor_t *pnp = pn_connection_acceptor(pn_cast(&c));
+                listener_context &lc(listener_context::get(pnp));
+                if (lc.ssl) {
+                    pn_ssl_t *ssl = pn_ssl(pnt);
+                    if (pn_ssl_init(ssl, server_domain.value.pn_domain(), NULL))
+                        throw error(MSG("server SSL/TLS initialization error"));
+                }
+#endif
+            }
             if (max_frame_size.set)
                 pn_transport_set_max_frame(pnt, max_frame_size.value);
             if (max_channels.set)
@@ -92,6 +113,10 @@ class connection_options::impl {
         heartbeat.override(x.heartbeat);
         container_id.override(x.container_id);
         reconnect.override(x.reconnect);
+        client_domain.override(x.client_domain);
+        server_domain.override(x.server_domain);
+        resume_id.override(x.resume_id);
+        peer_hostname.override(x.peer_hostname);
     }
 
 };
@@ -116,8 +141,14 @@ connection_options& connection_options::idle_timeout(uint32_t t) { impl_->idle_t
 connection_options& connection_options::heartbeat(uint32_t t) { impl_->heartbeat = t; return *this; }
 connection_options& connection_options::container_id(const std::string &id) { impl_->container_id = id; return *this; }
 connection_options& connection_options::reconnect(const reconnect_timer &rc) { impl_->reconnect = rc; return *this; }
+connection_options& connection_options::client_domain(const class client_domain &c) { impl_->client_domain = c; return *this; }
+connection_options& connection_options::server_domain(const class server_domain &c) { impl_->server_domain = c; return *this; }
+connection_options& connection_options::resume_id(const std::string &id) { impl_->resume_id = id; return *this; }
+connection_options& connection_options::peer_hostname(const std::string &name) { impl_->peer_hostname = name; return *this; }
 
 void connection_options::apply(connection& c) const { impl_->apply(c); }
+class client_domain &connection_options::client_domain() { return impl_->client_domain.value; }
+class server_domain &connection_options::server_domain() { return impl_->server_domain.value; }
 handler* connection_options::handler() const { return impl_->handler.value; }
 
 pn_connection_t* connection_options::pn_connection(connection &c) { return c.pn_object(); }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/src/container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container_impl.cpp b/proton-c/bindings/cpp/src/container_impl.cpp
index bb4f4c5..1ff734b 100644
--- a/proton-c/bindings/cpp/src/container_impl.cpp
+++ b/proton-c/bindings/cpp/src/container_impl.cpp
@@ -31,6 +31,7 @@
 #include "proton/sender.hpp"
 #include "proton/receiver.hpp"
 #include "proton/task.hpp"
+#include "proton/ssl.hpp"
 
 #include "msg.hpp"
 #include "container_impl.hpp"
@@ -186,28 +187,28 @@ receiver container_impl::open_receiver(const proton::url &url) {
 }
 
 acceptor container_impl::listen(const proton::url& url) {
-#ifdef PN_COMING_SOON
     connection_options opts = server_connection_options(); // Defaults
+#ifdef PN_COMING_SOON
     opts.override(user_opts);
+#endif
     handler *h = opts.handler();
     counted_ptr<pn_handler_t> chandler = h ? cpp_handler(h) : counted_ptr<pn_handler_t>();
-    pn_acceptor_t *acptr = pn_reactor_acceptor(
-        pn_cast(reactor_.get()), url.host().c_str(), url.port().c_str(), chandler.get());
-#else
-    acceptor acptr = reactor_.listen(url);
-#endif
+    pn_acceptor_t *acptr = pn_reactor_acceptor(reactor_.pn_object(), url.host().c_str(), url.port().c_str(), chandler.get());
     if (!acptr)
         throw error(MSG("accept fail: " <<
                         pn_error_text(pn_io_error(reactor_.pn_io())))
                         << "(" << url << ")");
-#ifdef PN_COMING_SOON
+#ifdef PROTON_1054_FIXED
     // Do not use pn_acceptor_set_ssl_domain().  Manage the incoming connections ourselves for
     // more flexibility (i.e. ability to change the server cert for a long running listener).
     listener_context& lc(listener_context::get(acptr));
     lc.connection_options = opts;
     lc.ssl = url.scheme() == url::AMQPS;
+#else
+    if (url.scheme() == url::AMQPS)
+        pn_acceptor_set_ssl_domain(acptr, server_connection_options_.server_domain().pn_domain());
 #endif
-    return acptr;
+    return acceptor(acptr);
 }
 
 std::string container_impl::next_link_name() {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/src/engine.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/engine.cpp b/proton-c/bindings/cpp/src/engine.cpp
index ad3d461..da3d0d9 100644
--- a/proton-c/bindings/cpp/src/engine.cpp
+++ b/proton-c/bindings/cpp/src/engine.cpp
@@ -57,7 +57,7 @@ struct engine::impl {
 };
 
 engine::engine(handler &h, const std::string& id_) : impl_(new impl(h, pn_transport())) {
-    if (!impl_->transport || !impl_->connection || !impl_->collector) 
+    if (!impl_->transport || !impl_->connection || !impl_->collector)
         throw error("engine setup failed");
     std::string id = id_.empty() ? uuid().str() : id_;
     pn_connection_set_container(impl_->connection, id.c_str());

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/src/ssl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/ssl.cpp b/proton-c/bindings/cpp/src/ssl.cpp
new file mode 100644
index 0000000..4c9138e
--- /dev/null
+++ b/proton-c/bindings/cpp/src/ssl.cpp
@@ -0,0 +1,75 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * 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
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "proton/ssl.hpp"
+#include "proton/error.hpp"
+#include "msg.hpp"
+
+#include "proton/ssl.h"
+
+namespace proton {
+
+std::string ssl::cipher() const {
+    char buf[128];
+    if (pn_ssl_get_cipher_name(object_, buf, sizeof(buf)))
+        return std::string(buf);
+    return std::string();
+}
+
+int ssl::ssf() const {
+    return pn_ssl_get_ssf(object_);
+}
+
+std::string ssl::protocol() const {
+    char buf[128];
+    if (pn_ssl_get_protocol_name(object_, buf, sizeof(buf)))
+        return std::string(buf);
+    return std::string();
+}
+
+ssl::resume_status_t ssl::resume_status() const {
+    return (ssl::resume_status_t) pn_ssl_resume_status(object_);
+}
+
+void ssl::peer_hostname(const std::string &hostname) {
+    if (pn_ssl_set_peer_hostname(object_, hostname.c_str()))
+        throw error(MSG("SSL set peer hostname failure for " << hostname));
+}
+
+std::string ssl::peer_hostname() const {
+    std::string hostname;
+    size_t len = 0;
+    if (pn_ssl_get_peer_hostname(object_, NULL, &len) || len == 0)
+        return hostname;
+    hostname.reserve(len);
+    if (!pn_ssl_get_peer_hostname(object_, const_cast<char *>(hostname.data()), &len))
+        hostname.resize(len - 1);
+    else
+        hostname.resize(0);
+    return hostname;
+}
+
+std::string ssl::remote_subject() const {
+    const char *s = pn_ssl_get_remote_subject(object_);
+    return s ? std::string(s) : std::string();
+}
+
+
+} // namespace

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/src/ssl_domain.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/ssl_domain.cpp b/proton-c/bindings/cpp/src/ssl_domain.cpp
new file mode 100644
index 0000000..ce50aa4
--- /dev/null
+++ b/proton-c/bindings/cpp/src/ssl_domain.cpp
@@ -0,0 +1,113 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * 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
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "proton/ssl.hpp"
+#include "proton/error.hpp"
+#include "msg.hpp"
+
+#include "proton/ssl.h"
+
+namespace proton {
+
+ssl_domain::ssl_domain(bool server_type) {
+    impl_ = pn_ssl_domain(server_type ? PN_SSL_MODE_SERVER : PN_SSL_MODE_CLIENT);
+    if (!impl_) throw error(MSG("SSL/TLS unavailable"));
+}
+
+ssl_domain::~ssl_domain() { pn_ssl_domain_free(impl_); }
+
+namespace {
+void set_cred(pn_ssl_domain_t *dom, const std::string &main, const std::string &extra, const std::string &pass, bool pwset) {
+    const char *cred2 = extra.empty() ? NULL : extra.c_str();
+    const char *pw = pwset ? pass.c_str() : NULL;
+    if (pn_ssl_domain_set_credentials(dom, main.c_str(), cred2, pw))
+        throw error(MSG("SSL certificate initialization failure for " << main << ":" <<
+                        (cred2 ? cred2 : "NULL") << ":" << (pw ? pw : "NULL")));
+}
+}
+
+server_domain::server_domain(ssl_certificate &cert) :
+    ssl_domain_(new ssl_domain(true)) {
+    set_cred(ssl_domain_->impl_, cert.certdb_main_, cert.certdb_extra_, cert.passwd_, cert.pw_set_);
+}
+
+server_domain::server_domain(ssl_certificate &cert, const std::string &trust_db, const std::string &advertise_db,
+                             ssl::verify_mode_t mode) :
+    ssl_domain_(new ssl_domain(true)) {
+    pn_ssl_domain_t *dom = ssl_domain_->impl_;
+    set_cred(dom, cert.certdb_main_, cert.certdb_extra_, cert.passwd_, cert.pw_set_);
+    if (pn_ssl_domain_set_trusted_ca_db(dom, trust_db.c_str()))
+        throw error(MSG("SSL trust store initialization failure for " << trust_db));
+    const std::string &db = advertise_db.empty() ? trust_db : advertise_db;
+    if (pn_ssl_domain_set_peer_authentication(dom, (pn_ssl_verify_mode_t) mode, db.c_str()))
+        throw error(MSG("SSL server configuration failure requiring client certificates using " << db));
+}
+
+// Keep default constructor low overhead for default use in connection_options.
+server_domain::server_domain() : ssl_domain_(0) {}
+
+pn_ssl_domain_t* server_domain::pn_domain() {
+    if (!ssl_domain_) {
+        // Lazily create anonymous domain context (no cert).  Could make it a singleton, but rare use?
+        ssl_domain_.reset(new ssl_domain(true));
+    }
+    return ssl_domain_->impl_;
+}
+
+namespace {
+void client_setup(pn_ssl_domain_t *dom, const std::string &trust_db, ssl::verify_mode_t mode) {
+    if (pn_ssl_domain_set_trusted_ca_db(dom, trust_db.c_str()))
+        throw error(MSG("SSL trust store initialization failure for " << trust_db));
+    if (pn_ssl_domain_set_peer_authentication(dom, (pn_ssl_verify_mode_t) mode, NULL))
+        throw error(MSG("SSL client verify mode failure"));
+}
+}
+
+client_domain::client_domain(const std::string &trust_db, ssl::verify_mode_t mode) :
+    ssl_domain_(new ssl_domain(false)) {
+    client_setup(ssl_domain_->impl_, trust_db, mode);
+}
+
+client_domain::client_domain(ssl_certificate &cert, const std::string &trust_db, ssl::verify_mode_t mode) :
+    ssl_domain_(new ssl_domain(false)) {
+    pn_ssl_domain_t *dom = ssl_domain_->impl_;
+    set_cred(dom, cert.certdb_main_, cert.certdb_extra_, cert.passwd_, cert.pw_set_);
+    client_setup(dom, trust_db, mode);
+}
+
+client_domain::client_domain() : ssl_domain_(0) {}
+
+pn_ssl_domain_t* client_domain::pn_domain() {
+    if (!ssl_domain_) {
+        // Lazily create anonymous domain context (no CA).  Could make it a singleton, but rare use?
+        ssl_domain_.reset(new ssl_domain(false));
+    }
+    return ssl_domain_->impl_;
+}
+
+
+ssl_certificate::ssl_certificate(const std::string &main, const std::string &extra)
+    : certdb_main_(main), certdb_extra_(extra), pw_set_(false) {}
+
+ssl_certificate::ssl_certificate(const std::string &main, const std::string &extra, const std::string &pw)
+    : certdb_main_(main), certdb_extra_(extra), passwd_(pw), pw_set_(true) {}
+
+
+} // namespace

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/cf784e2a/proton-c/bindings/cpp/src/transport.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/transport.cpp b/proton-c/bindings/cpp/src/transport.cpp
index 0574663..f6ccfa0 100644
--- a/proton-c/bindings/cpp/src/transport.cpp
+++ b/proton-c/bindings/cpp/src/transport.cpp
@@ -20,6 +20,7 @@
  */
 #include "proton/transport.hpp"
 #include "proton/connection.hpp"
+#include "proton/ssl.hpp"
 #include "msg.hpp"
 #include "proton/transport.h"
 
@@ -29,6 +30,10 @@ connection transport::connection() const {
     return pn_transport_connection(pn_object());
 }
 
+class ssl transport::ssl() const {
+    return proton::ssl(pn_ssl(pn_object()));
+}
+
 void transport::unbind() {
     if (pn_transport_unbind(pn_object()))
         throw error(MSG("transport::unbind failed " << pn_error_text(pn_transport_error(pn_object()))));


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org