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/12/02 09:01:03 UTC

qpid-proton git commit: PROTON-1053: sasl support for C++ binding

Repository: qpid-proton
Updated Branches:
  refs/heads/master eb63824fd -> 0ebf1d40e


PROTON-1053: sasl 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/0ebf1d40
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/0ebf1d40
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/0ebf1d40

Branch: refs/heads/master
Commit: 0ebf1d40e49ac95915c47ffc7901e29febb4c739
Parents: eb63824
Author: Clifford Jansen <cl...@apache.org>
Authored: Tue Dec 1 23:55:10 2015 -0800
Committer: Clifford Jansen <cl...@apache.org>
Committed: Tue Dec 1 23:55:49 2015 -0800

----------------------------------------------------------------------
 examples/cpp/CMakeLists.txt                     |   1 +
 examples/cpp/ssl.cpp                            |   4 -
 examples/cpp/ssl_client_cert.cpp                | 176 +++++++++++++++++++
 proton-c/bindings/cpp/CMakeLists.txt            |   1 +
 .../bindings/cpp/include/proton/connection.hpp  |   5 +
 .../cpp/include/proton/connection_options.hpp   |  10 +-
 proton-c/bindings/cpp/include/proton/sasl.hpp   |  60 +++++++
 .../bindings/cpp/include/proton/transport.hpp   |   4 +-
 proton-c/bindings/cpp/src/connection.cpp        |   4 +
 .../bindings/cpp/src/connection_options.cpp     |  33 +++-
 proton-c/bindings/cpp/src/connector.cpp         |   5 +
 proton-c/bindings/cpp/src/container_impl.cpp    |  14 +-
 proton-c/bindings/cpp/src/sasl.cpp              |  47 +++++
 proton-c/bindings/cpp/src/transport.cpp         |   6 +-
 14 files changed, 345 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/examples/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt
index 3858df3..903294c 100644
--- a/examples/cpp/CMakeLists.txt
+++ b/examples/cpp/CMakeLists.txt
@@ -37,6 +37,7 @@ set(examples
   recurring_timer
   connection_options
   ssl
+  ssl_client_cert
   encode_decode)
 
 if (NOT WIN32)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/examples/cpp/ssl.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl.cpp b/examples/cpp/ssl.cpp
index f81eb62..13ad76f 100644
--- a/examples/cpp/ssl.cpp
+++ b/examples/cpp/ssl.cpp
@@ -76,10 +76,6 @@ class hello_world_direct : public proton::messaging_handler {
         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);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/examples/cpp/ssl_client_cert.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_client_cert.cpp b/examples/cpp/ssl_client_cert.cpp
new file mode 100644
index 0000000..412162a
--- /dev/null
+++ b/examples/cpp/ssl_client_cert.cpp
@@ -0,0 +1,176 @@
+/*
+ *
+ * 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 "proton/sasl.hpp"
+
+#include <iostream>
+
+using proton::connection_options;
+using proton::client_domain;
+using proton::server_domain;
+using proton::ssl_certificate;
+using proton::sasl;
+
+// 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 inbound_listener;
+
+    void on_connection_opened(proton::event &e) {
+        std::cout << "Inbound server connection connected via SSL.  Protocol: " << 
+            e.connection().transport().ssl().protocol() << std::endl;
+        if (e.connection().transport().sasl().outcome() == sasl::OK)
+            std::cout << "Inbound client certificate subject is " << 
+                e.connection().transport().ssl().remote_subject() << std::endl;
+        else {
+            std::cout << "Inbound client authentication failed" <<std::endl;
+            e.connection().close();
+        }
+	inbound_listener.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");
+	std::string client_CA = platform_CA("tclient");
+        // Specify an SSL domain with CA's for client certificate verification.
+        server_domain sdomain(server_cert, client_CA);
+        connection_options server_opts;
+        server_opts.server_domain(sdomain).handler(&s_handler);
+	server_opts.allowed_mechs("EXTERNAL");
+        e.container().server_connection_options(server_opts);
+
+        // Configure client.
+	ssl_certificate client_cert = platform_certificate("tclient", "tclientpw");
+	std::string server_CA = platform_CA("tserver");
+	client_domain cdomain(client_cert, server_CA);
+        connection_options client_opts;
+        client_opts.client_domain(cdomain).allowed_mechs("EXTERNAL");
+        // Validate the server certificate against this name:
+        client_opts.peer_hostname("test_server");
+        e.container().client_connection_options(client_opts);
+
+        s_handler.inbound_listener = 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/0ebf1d40/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index 6bc6445..bcdc61b 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -62,6 +62,7 @@ set(qpid-proton-cpp-source
   src/receiver.cpp
   src/reconnect_timer.cpp
   src/request_response.cpp
+  src/sasl.cpp
   src/sender.cpp
   src/session.cpp
   src/ssl.cpp

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/proton-c/bindings/cpp/include/proton/connection.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/connection.hpp b/proton-c/bindings/cpp/include/proton/connection.hpp
index cc8c5ba..338e542 100644
--- a/proton-c/bindings/cpp/include/proton/connection.hpp
+++ b/proton-c/bindings/cpp/include/proton/connection.hpp
@@ -107,6 +107,11 @@ class connection : public object<pn_connection_t>, endpoint
     /** Get the endpoint state */
     PN_CPP_EXTERN endpoint::state state() const;
 
+  private:
+    PN_CPP_EXTERN void user(const std::string &);
+    PN_CPP_EXTERN void password(const std::string &);
+
+    
     friend class connection_options;
     friend class connector;
     friend class transport;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/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 c9701c9..6c78f54 100644
--- a/proton-c/bindings/cpp/include/proton/connection_options.hpp
+++ b/proton-c/bindings/cpp/include/proton/connection_options.hpp
@@ -75,20 +75,16 @@ class connection_options {
     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 &);
-#endif
+    PN_CPP_EXTERN connection_options& sasl_config_name(const std::string &);
+    PN_CPP_EXTERN connection_options& sasl_config_path(const std::string &);
+
   private:
     void apply(connection&) const;
     class handler* handler() const;
     static pn_connection_t *pn_connection(connection &);
-#ifdef PN_CPP_SOON
-    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();
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/proton-c/bindings/cpp/include/proton/sasl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/sasl.hpp b/proton-c/bindings/cpp/include/proton/sasl.hpp
new file mode 100644
index 0000000..4432d8d
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/sasl.hpp
@@ -0,0 +1,60 @@
+#ifndef PROTON_CPP_SASL_H
+#define PROTON_CPP_SASL_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/sasl.h"
+#include <string>
+
+namespace proton {
+
+class sasl {
+  public:
+    /** The result of the SASL negotiation */
+    enum outcome_t {
+        NONE = PN_SASL_NONE,   /** negotiation not completed */
+        OK = PN_SASL_OK,       /** authentication succeeded */
+        AUTH = PN_SASL_AUTH,   /** failed due to bad credentials */
+        SYS = PN_SASL_SYS,     /** failed due to a system error */
+        PERM = PN_SASL_PERM,   /** failed due to unrecoverable error */
+        TEMP = PN_SASL_TEMP    /** failed due to transient error */
+    };
+
+    sasl(pn_sasl_t* s) : object_(s) {}
+    PN_CPP_EXTERN static bool extended();
+    PN_CPP_EXTERN void done(outcome_t);
+    PN_CPP_EXTERN outcome_t outcome() const;
+    PN_CPP_EXTERN std::string user() const;
+    PN_CPP_EXTERN std::string mech() const;
+
+    PN_CPP_EXTERN void allow_insecure_mechs(bool);
+    PN_CPP_EXTERN bool allow_insecure_mechs();
+    PN_CPP_EXTERN void allowed_mechs(const std::string &);
+    PN_CPP_EXTERN void config_name(const std::string&);
+    PN_CPP_EXTERN void config_path(const std::string&);
+private:
+    pn_sasl_t* object_;
+};
+
+}
+
+#endif  /*!PROTON_CPP_SASL_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/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 3f664bc..971913b 100644
--- a/proton-c/bindings/cpp/include/proton/transport.hpp
+++ b/proton-c/bindings/cpp/include/proton/transport.hpp
@@ -31,6 +31,7 @@ struct pn_transport_t;
 namespace proton {
 
 class connection;
+class sasl;
 
 /** Represents a connection transport */
 class transport : public object<pn_transport_t>
@@ -39,6 +40,8 @@ class transport : public object<pn_transport_t>
     transport(pn_transport_t* t) : object<pn_transport_t>(t) {}
 
     PN_CPP_EXTERN class connection connection() const;
+    PN_CPP_EXTERN class ssl ssl() const;
+    PN_CPP_EXTERN class sasl sasl() const;
     PN_CPP_EXTERN void unbind();
     PN_CPP_EXTERN void bind(class connection &);
     PN_CPP_EXTERN uint32_t max_frame_size() const;
@@ -47,7 +50,6 @@ 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/0ebf1d40/proton-c/bindings/cpp/src/connection.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection.cpp b/proton-c/bindings/cpp/src/connection.cpp
index 733face..508a013 100644
--- a/proton-c/bindings/cpp/src/connection.cpp
+++ b/proton-c/bindings/cpp/src/connection.cpp
@@ -110,4 +110,8 @@ receiver connection::open_receiver(const std::string &addr, bool dynamic, handle
 
 endpoint::state connection::state() const { return pn_connection_state(pn_object()); }
 
+void connection::user(const std::string &name) { pn_connection_set_user(pn_object(), name.c_str()); }
+
+void connection::password(const std::string &pass) { pn_connection_set_password(pn_object(), pass.c_str()); }
+
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/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 5097e42..141ffc9 100644
--- a/proton-c/bindings/cpp/src/connection_options.cpp
+++ b/proton-c/bindings/cpp/src/connection_options.cpp
@@ -22,6 +22,7 @@
 #include "proton/reconnect_timer.hpp"
 #include "proton/transport.hpp"
 #include "proton/ssl.hpp"
+#include "proton/sasl.hpp"
 #include "contexts.hpp"
 #include "connector.hpp"
 #include "msg.hpp"
@@ -52,11 +53,11 @@ class connection_options::impl {
     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;
-#endif
+    option<std::string> sasl_config_name;
+    option<std::string> sasl_config_path;
 
     void apply(connection& c) {
         pn_connection_t *pnc = connection_options::pn_connection(c);
@@ -69,6 +70,7 @@ class connection_options::impl {
         // transport not yet configured.
         if (pnt && (uninit || (outbound && !outbound->transport_configured())))
         {
+            // SSL
             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();
@@ -89,6 +91,22 @@ class connection_options::impl {
                 }
 #endif
             }
+
+            // SASL
+            transport t = c.transport();
+            if (!sasl_enabled.set || sasl_enabled.value) {
+                if (sasl_enabled.set)  // Explicitly set, not just default behaviour.
+                    t.sasl();          // Force a sasl instance.  Lazily create one otherwise.
+                if (allow_insecure_mechs.set)
+                    t.sasl().allow_insecure_mechs(allow_insecure_mechs.value);
+                if (allowed_mechs.set)
+                    t.sasl().allowed_mechs(allowed_mechs.value);
+                if (sasl_config_name.set)
+                    t.sasl().config_name(sasl_config_name.value);
+                if (sasl_config_path.set)
+                    t.sasl().config_path(sasl_config_path.value);
+            }
+
             if (max_frame_size.set)
                 pn_transport_set_max_frame(pnt, max_frame_size.value);
             if (max_channels.set)
@@ -117,6 +135,11 @@ class connection_options::impl {
         server_domain.override(x.server_domain);
         resume_id.override(x.resume_id);
         peer_hostname.override(x.peer_hostname);
+        sasl_enabled.override(x.sasl_enabled);
+        allow_insecure_mechs.override(x.allow_insecure_mechs);
+        allowed_mechs.override(x.allowed_mechs);
+        sasl_config_name.override(x.sasl_config_name);
+        sasl_config_path.override(x.sasl_config_path);
     }
 
 };
@@ -145,11 +168,15 @@ connection_options& connection_options::client_domain(const class client_domain
 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; }
+connection_options& connection_options::sasl_enabled(bool b) { impl_->sasl_enabled = b; return *this; }
+connection_options& connection_options::allow_insecure_mechs(bool b) { impl_->allow_insecure_mechs = b; return *this; }
+connection_options& connection_options::allowed_mechs(const std::string &s) { impl_->allowed_mechs = s; return *this; }
+connection_options& connection_options::sasl_config_name(const std::string &n) { impl_->sasl_config_name = n; return *this; }
+connection_options& connection_options::sasl_config_path(const std::string &p) { impl_->sasl_config_path = p; 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(); }
 } // namespace proton

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/proton-c/bindings/cpp/src/connector.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connector.cpp b/proton-c/bindings/cpp/src/connector.cpp
index 90a16e6..e2bb802 100644
--- a/proton-c/bindings/cpp/src/connector.cpp
+++ b/proton-c/bindings/cpp/src/connector.cpp
@@ -27,6 +27,7 @@
 #include "proton/url.hpp"
 #include "proton/reconnect_timer.hpp"
 #include "proton/task.hpp"
+#include "proton/sasl.hpp"
 #include "container_impl.hpp"
 
 #include "proton/connection.h"
@@ -62,6 +63,10 @@ void connector::connect() {
     connection_.host(address_.host_port());
     pn_transport_t *pnt = pn_transport();
     transport t(pnt);
+    if (!address_.username().empty())
+        connection_.user(address_.username());
+    if (!address_.password().empty())
+        connection_.password(address_.password());
     t.bind(connection_);
     pn_decref((void *)pnt);
     // Apply options to the new transport.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/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 1ff734b..7d64ebc 100644
--- a/proton-c/bindings/cpp/src/container_impl.cpp
+++ b/proton-c/bindings/cpp/src/container_impl.cpp
@@ -32,6 +32,8 @@
 #include "proton/receiver.hpp"
 #include "proton/task.hpp"
 #include "proton/ssl.hpp"
+#include "proton/sasl.hpp"
+#include "proton/transport.hpp"
 
 #include "msg.hpp"
 #include "container_impl.hpp"
@@ -234,21 +236,15 @@ void container_impl::server_connection_options(const connection_options &opts) {
 }
 
 void container_impl::configure_server_connection(connection &c) {
-#ifdef PN_COMING_SOON
+#ifdef PN_1054_FIXED
     pn_acceptor_t *pnp = pn_connection_acceptor(pn_cast(&c));
     listener_context &lc(listener_context::get(pnp));
     class connection_options &opts(lc.connection_options);
-    if (opts.sasl_enabled()) {
-        sasl &s(c.transport().sasl());
-        s.allow_insecure_mechs(opts.allow_insecure_mechs());
-        if (opts.allowed_mechs())
-            s.allowed_mechs(*opts.allowed_mechs());
-    }
-    opts.apply(c);
 #else
     // Can't distinguish between multiple listeners yet.  See PROTON-1054
-    server_connection_options_.apply(c);
+    class connection_options &opts(server_connection_options_);
 #endif
+    opts.apply(c);
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/proton-c/bindings/cpp/src/sasl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/sasl.cpp b/proton-c/bindings/cpp/src/sasl.cpp
new file mode 100644
index 0000000..9638a52
--- /dev/null
+++ b/proton-c/bindings/cpp/src/sasl.cpp
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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/sasl.hpp"
+
+namespace proton {
+
+bool sasl::extended() { return pn_sasl_extended(); }
+void sasl::done(outcome_t outcome) { pn_sasl_done(object_, static_cast<pn_sasl_outcome_t>(outcome)); }
+sasl::outcome_t sasl::outcome() const { return static_cast<outcome_t>(pn_sasl_outcome(object_)); }
+
+std::string sasl::user() const {
+    const char *name = pn_sasl_get_user(object_);
+    return name ? std::string(name) : std::string();
+}
+
+std::string sasl::mech() const {
+    const char *m = pn_sasl_get_mech(object_);
+    return m ? std::string(m) : std::string();
+}
+
+void sasl::allow_insecure_mechs(bool allowed) { pn_sasl_set_allow_insecure_mechs(object_, allowed); }
+bool sasl::allow_insecure_mechs() { return pn_sasl_get_allow_insecure_mechs(object_); }
+void sasl::allowed_mechs(const std::string &mechs) { pn_sasl_allowed_mechs(object_, mechs.c_str()); }
+void sasl::config_name(const std::string &name) { pn_sasl_config_name(object_, name.c_str()); }
+void sasl::config_path(const std::string &path) { pn_sasl_config_path(object_, path.c_str()); }
+
+
+} // namespace

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0ebf1d40/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 f6ccfa0..4db78d0 100644
--- a/proton-c/bindings/cpp/src/transport.cpp
+++ b/proton-c/bindings/cpp/src/transport.cpp
@@ -21,6 +21,7 @@
 #include "proton/transport.hpp"
 #include "proton/connection.hpp"
 #include "proton/ssl.hpp"
+#include "proton/sasl.hpp"
 #include "msg.hpp"
 #include "proton/transport.h"
 
@@ -34,13 +35,16 @@ class ssl transport::ssl() const {
     return proton::ssl(pn_ssl(pn_object()));
 }
 
+class sasl transport::sasl() const {
+    return proton::sasl(pn_sasl(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()))));
 }
 
 void transport::bind(class connection &conn) {
-//    pn_connection_t *c = static_cast<pn_connection_t*>(conn.object_);
     if (pn_transport_bind(pn_object(), conn.pn_object()))
         throw error(MSG("transport::bind 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