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 <cliffjan...@apache.org> Authored: Sun Nov 29 23:11:11 2015 -0800 Committer: Clifford Jansen <cliffjan...@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-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org