You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kg...@apache.org on 2012/09/19 17:32:51 UTC

svn commit: r1387642 - in /qpid/proton/branches/openssl: examples/mailbox/ proton-c/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ proton-c/src/engine/ proton-c/src/ssl/

Author: kgiusti
Date: Wed Sep 19 15:32:50 2012
New Revision: 1387642

URL: http://svn.apache.org/viewvc?rev=1387642&view=rev
Log:
PROTON-2: support for SSL/TLS using OpenSSL.

Added:
    qpid/proton/branches/openssl/examples/mailbox/ssl-setup.sh   (with props)
    qpid/proton/branches/openssl/proton-c/include/proton/ssl.h   (with props)
    qpid/proton/branches/openssl/proton-c/src/ssl/
    qpid/proton/branches/openssl/proton-c/src/ssl/openssl.c   (with props)
    qpid/proton/branches/openssl/proton-c/src/ssl/ssl-internal.h   (with props)
    qpid/proton/branches/openssl/proton-c/src/ssl/ssl_stub.c   (with props)
Modified:
    qpid/proton/branches/openssl/examples/mailbox/README.txt
    qpid/proton/branches/openssl/examples/mailbox/fetch
    qpid/proton/branches/openssl/examples/mailbox/post
    qpid/proton/branches/openssl/examples/mailbox/server
    qpid/proton/branches/openssl/proton-c/CMakeLists.txt
    qpid/proton/branches/openssl/proton-c/bindings/php/php.i
    qpid/proton/branches/openssl/proton-c/bindings/python/python.i
    qpid/proton/branches/openssl/proton-c/bindings/ruby/ruby.i
    qpid/proton/branches/openssl/proton-c/include/proton/cproton.i
    qpid/proton/branches/openssl/proton-c/include/proton/driver.h
    qpid/proton/branches/openssl/proton-c/pn_config.h.in
    qpid/proton/branches/openssl/proton-c/src/driver.c
    qpid/proton/branches/openssl/proton-c/src/engine/engine-internal.h
    qpid/proton/branches/openssl/proton-c/src/engine/engine.c

Modified: qpid/proton/branches/openssl/examples/mailbox/README.txt
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/examples/mailbox/README.txt?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/examples/mailbox/README.txt (original)
+++ qpid/proton/branches/openssl/examples/mailbox/README.txt Wed Sep 19 15:32:50 2012
@@ -39,3 +39,28 @@ To run the example:
     use the --help option for additional details.
 
     Once you are done running the example, you may stop the server application.
+
+
+Optional - using SSL to encrypt the data connections between the server and the clients:
+
+    The Proton driver library has support for SSL/TLS [1].  The mailbox example can be
+    configured to use SSL to encypt the connections between the server and the post/fetch
+    clients.
+
+    Use the ssl-setup.sh script to create the trusted certificates database, and an
+    identifying certificate for the server.
+
+    Once ssl-setup.sh has created all the necessary certificates, you supply the server
+    with these parameters:
+
+    $ server --ssl-cert-file ./server-certificate.pem --ssl-key-file ./server-private-key.pem --require-encryption --ssl-cert-db ./trusted_db --ssl-key-pw "trustno1"
+
+    And give the fetch/post clients the path to the database containing the trusted
+    certificates:
+
+    $ post -m myMailbox --ssl-cert-db ./trusted_db "Here is a message"
+    $ fetch --ssl-cert-db ./trusted_db  myMailbox
+
+
+[1] At the time of this writing SSL/TLS is implemented using OpenSSL, and is only
+available on those platforms that support the OpenSSL libraries.

Modified: qpid/proton/branches/openssl/examples/mailbox/fetch
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/examples/mailbox/fetch?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/examples/mailbox/fetch (original)
+++ qpid/proton/branches/openssl/examples/mailbox/fetch Wed Sep 19 15:32:50 2012
@@ -35,12 +35,23 @@ class Options(object):
         parser.add_option("-v", "--verbose", action="store_true",
                           help="Turn on extra trace messages.")
 
+        # SSL configuration
+        parser.add_option("--ssl-cert-db", type="str", metavar="<dir>",
+                          help="database of trusted certificates. Enables use of SSL.")
+
+        # if server wants authentication:
+        #parser.add_option("--ssl-cert-file")
+        #parser.add_option("--ssl-key-file")
+        #parser.add_option("--ssl-key-pw")
+
         opts, mailboxes = parser.parse_args()   # uses sys.argv[1:]
 
         self.mailbox = None
         if len(mailboxes) == 1:
             self.mailbox = str(mailboxes[0])
         self.server = opts.server
+        self.ca_database = opts.ssl_cert_db
+
         addr = opts.server.rsplit(":", 1)
         self.host = addr[0]
         if len(addr) == 2:
@@ -52,7 +63,7 @@ class Options(object):
 
 
 class FetchClient(object):
-    def __init__(self, host, port, mailbox):
+    def __init__(self, host, port, mailbox, ca_database=None):
         """ Initialize the client by supplying the address of the server, and
         the name of the mailbox to fetch from.
         """
@@ -60,6 +71,8 @@ class FetchClient(object):
         self.port = port
         self.mailbox = mailbox
         self.logging = False
+        self.ca_database = ca_database
+        self.ssl_client = None
 
     def setup(self):
         """ Setup and configure the connection to the server.
@@ -70,6 +83,18 @@ class FetchClient(object):
         self.driver = pn_driver();
         self.cxtr = pn_connector(self.driver, self.host, self.port, None)
 
+        # Enable SSL if database of trusted CAs given
+        if self.ca_database:
+            self.log("Using SSL, CA database = %s" % self.ca_database)
+
+            ssl_client = pn_connector_ssl(self.cxtr)
+            assert(ssl_client)
+            rc = pn_ssl_set_trusted_ca_db(ssl_client, self.ca_database)
+            assert(rc == 0)
+            # we want to fail if the server's certificate is invalid:
+            rc = pn_ssl_set_peer_authentication(ssl_client, PN_SSL_VERIFY_PEER, None)
+            assert(rc == 0)
+
         # configure SASL
         self.sasl = pn_connector_sasl(self.cxtr)
         pn_sasl_mechanisms(self.sasl, "ANONYMOUS")
@@ -91,6 +116,25 @@ class FetchClient(object):
         pn_link_open(self.link)
 
 
+    def teardown(self):
+        """ Perform a clean disconnect from the server, and release the
+        resources created in setup()
+        """
+        self.log("Shutting down the connection cleanly...")
+        pn_connection_close(self.conn)
+
+        # now wait for the connector to close
+        while not (pn_connector_closed(self.cxtr)):
+            self.wait()
+
+        #pn_sasl_free(self.sasl);
+        pn_link_free(self.link);
+        pn_session_free(self.ssn);
+        pn_connection_free(self.conn);
+        pn_connector_free(self.cxtr);
+        self.log("...Shutdown complete!")
+
+
     def wait(self):
         """ Wait for an event to process.
         """
@@ -123,6 +167,10 @@ class FetchClient(object):
             d = _next
 
 
+    def closed(self):
+        return self.cxtr == None or pn_connector_closed(self.cxtr)
+
+
     def enableLogging(self):
         self.logging = True
 
@@ -146,7 +194,8 @@ def main():
 
     receiver = FetchClient(options.host,
                            options.port,
-                           options.mailbox)
+                           options.mailbox,
+                           options.ca_database)
     if options.verbose:
         receiver.enableLogging()
 
@@ -155,6 +204,9 @@ def main():
     # wait until we authenticate with the server
     while pn_sasl_state(receiver.sasl) not in (PN_SASL_PASS, PN_SASL_FAIL):
         receiver.wait()
+        if receiver.closed():
+            receiver.log("connection failed")
+            return -1;
 
     if pn_sasl_state(receiver.sasl) == PN_SASL_FAIL:
         print("Error: Authentication failure")
@@ -163,6 +215,9 @@ def main():
     # wait until the server has opened the connection
     while not (pn_link_state(receiver.link) & PN_REMOTE_ACTIVE):
         receiver.wait()
+        if receiver.closed():
+            receiver.log("connection failed")
+            return -1;
 
     # check if the server recognizes the mailbox, fail if it does not
     if pn_remote_source(receiver.link) != options.mailbox:
@@ -176,7 +231,7 @@ def main():
     # main loop: continue fetching messages until 'count' messages have been
     # retrieved
 
-    while pn_credit(receiver.link) > 0:    # while all msgs have not arrived
+    while pn_credit(receiver.link) > 0 and not receiver.closed():    # while all msgs have not arrived
         if pn_queued(receiver.link) == 0:  # wait for some to arrive
             receiver.wait()
 
@@ -198,14 +253,13 @@ def main():
         receiver.settle()
 
     # block until any leftover deliveries are settled
-    while pn_unsettled(receiver.link) > 0:
+    while pn_unsettled(receiver.link) > 0 and not receiver.closed():
         receiver.wait()
         receiver.settle()
 
-    # we're done, close and wait for the remote to close also
-    pn_connection_close(receiver.conn)
-    while not (pn_connection_state(receiver.conn) & PN_REMOTE_CLOSED):
-        receiver.wait()
+    # we're done, now clean up the connection:
+    receiver.teardown()
+
     return 0
 
 

Modified: qpid/proton/branches/openssl/examples/mailbox/post
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/examples/mailbox/post?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/examples/mailbox/post (original)
+++ qpid/proton/branches/openssl/examples/mailbox/post Wed Sep 19 15:32:50 2012
@@ -36,10 +36,21 @@ class Options(object):
         parser.add_option("-v", "--verbose", action="store_true",
                           help="Turn on extra trace messages.")
 
+        # SSL configuration
+        parser.add_option("--ssl-cert-db", type="str", metavar="<dir>",
+                          help="database of trusted certificates.  Enables use of SSL.")
+
+        # if server wants client authentication:
+        #parser.add_option("--ssl-cert-file")
+        #parser.add_option("--ssl-key-file")
+        #parser.add_option("--ssl-key-pw")
+
+
         opts, self.messages = parser.parse_args()   # uses sys.argv[1:]
 
         self.server = opts.server
         self.mailbox = opts.mailbox
+        self.ca_database = opts.ssl_cert_db
 
         addr = opts.server.rsplit(":", 1)
         self.host = addr[0]
@@ -51,7 +62,7 @@ class Options(object):
 
 
 class PostClient(object):
-    def __init__(self, host, port, mailbox):
+    def __init__(self, host, port, mailbox, ca_database=None):
         """ Initialize the client by supplying the address of the server, and
         the name of the mailbox to post to.
         """
@@ -59,6 +70,9 @@ class PostClient(object):
         self.port = port
         self.mailbox = mailbox
         self.logging = False
+        self.ca_database = ca_database
+        self.ssl_client = None
+
 
     def setup(self):
         """ Setup and configure the connection to the server.
@@ -68,6 +82,19 @@ class PostClient(object):
         self.log("Connecting to server host = %s:%s" % (self.host, self.port))
         self.driver = pn_driver();
         self.cxtr = pn_connector(self.driver, self.host, self.port, None)
+        assert(self.cxtr)
+
+        # Enable SSL if database of trusted CAs given
+        if self.ca_database:
+            self.log("Using SSL, CA database = %s" % self.ca_database)
+
+            ssl_client = pn_connector_ssl(self.cxtr)
+            assert(ssl_client)
+            rc = pn_ssl_set_trusted_ca_db(ssl_client, self.ca_database)
+            assert(rc == 0)
+            # we want to fail if the server's certificate is invalid:
+            rc = pn_ssl_set_peer_authentication(ssl_client, PN_SSL_VERIFY_PEER, None)
+            assert(rc == 0)
 
         # configure SASL
         self.sasl = pn_connector_sasl(self.cxtr)
@@ -90,6 +117,25 @@ class PostClient(object):
         pn_link_open(self.link)
 
 
+    def teardown(self):
+        """ Perform a clean disconnect from the server, and release the
+        resources created in setup()
+        """
+        self.log("Shutting down the connection cleanly...")
+        pn_connection_close(self.conn)
+
+        # now wait for the connector to close
+        while not pn_connector_closed(self.cxtr):
+            self.wait()
+
+        #pn_sasl_free(self.sasl);
+        pn_link_free(self.link);
+        pn_session_free(self.ssn);
+        pn_connection_free(self.conn);
+        pn_connector_free(self.cxtr);
+        self.log("...Shutdown complete!")
+
+
     def wait(self):
         """ Wait for an event to process.
         """
@@ -125,6 +171,10 @@ class PostClient(object):
             d = _next
 
 
+    def closed(self):
+        return self.cxtr == None or pn_connector_closed(self.cxtr)
+
+
     def enableLogging(self):
         self.logging = True
 
@@ -148,7 +198,8 @@ def main():
 
     sender = PostClient(options.host,
                         options.port,
-                        options.mailbox)
+                        options.mailbox,
+                        options.ca_database)
     if options.verbose:
         sender.enableLogging()
 
@@ -157,6 +208,9 @@ def main():
     # wait until we authenticate with the server
     while pn_sasl_state(sender.sasl) not in (PN_SASL_PASS, PN_SASL_FAIL):
         sender.wait()
+        if sender.closed():
+            sender.log("connection failed")
+            return -1;
 
     if pn_sasl_state(sender.sasl) == PN_SASL_FAIL:
         print("Error: Authentication failure")
@@ -166,12 +220,12 @@ def main():
 
     pendingSends = list(options.messages)
     while pendingSends:
-        # wait until the server grands us some send credit
+        # wait until the server grants us some send credit
         if pn_credit(sender.link) == 0:
             sender.log("wait for credit")
             sender.wait()
 
-        while pn_credit(sender.link) > 0:
+        while pn_credit(sender.link) > 0 and not sender.closed():
             msg = pendingSends.pop(0)
             sender.log("sending %s" % msg)
             d = pn_delivery(sender.link, "post-delivery-%s" % len(pendingSends))
@@ -186,14 +240,14 @@ def main():
         sender.settle()
 
     # done sending, now block until any pending deliveries are settled
-    while pn_unsettled(sender.link) > 0:
+    sender.log("Done sending messages, waiting for deliveries to settle...");
+    while pn_unsettled(sender.link) > 0 and not sender.closed():
         sender.wait()
         sender.settle()
 
-    # we're done, close and wait for the remote to close also
-    pn_connection_close(sender.conn)
-    while not (pn_connection_state(sender.conn) & PN_REMOTE_CLOSED):
-        sender.wait()
+    # We're done - now clean up the connection:
+    sender.teardown()
+
     return 0
 
 

Modified: qpid/proton/branches/openssl/examples/mailbox/server
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/examples/mailbox/server?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/examples/mailbox/server (original)
+++ qpid/proton/branches/openssl/examples/mailbox/server Wed Sep 19 15:32:50 2012
@@ -36,12 +36,37 @@ class Options(object):
     def __init__(self):
         parser = OptionParser(usage="usage: %prog [options] <server-address>")
         parser.add_option("-v", "--verbose",
-                          action="store_false", dest="verbose", default=True,
+                          action="store_true", dest="verbose",
                           help="print status messages to stdout")
+        # SSL configuration
+        parser.add_option("--ssl-cert-file", type="str", metavar="<file>",
+                          help="PEM file containing identifying certificate.")
+        parser.add_option("--ssl-key-file", type="str", metavar="<file>",
+                          help="PEM file containing private key of certificate.")
+        parser.add_option("--ssl-key-pw", type="str", metavar='"password"',
+                          help="key file password (if key encrypted).")
+        parser.add_option("--require-encryption", action="store_true",
+                          help="Do not accept connections from clients that do not use encryption.")
+        parser.add_option("--ssl-cert-db", type="str", metavar="<dir>",
+                          help="database of trusted certificates. Used to authenticate clients.")
+
+        # For client authentication using SSL:
+        #parser.add_option("-c", "--ssl-require-client-authentication", action="store_true", help="force client to authenticate itself.")
+        #parser.add_option("-t", "--ssl-trusted-CA-file", type="str", metavar="<file>", help="file holding certificates of CAs to advertise")
 
         opts, self.server = parser.parse_args()   # uses sys.argv[1:]
         self.verbose = opts.verbose
 
+        if opts.ssl_cert_file:
+            if not opts.ssl_key_file:
+                print("Error: if --ssl-cert-file given, --ssl-key-file must be supplied!");
+                sys.exit(-1)
+        self.certificate_file = opts.ssl_cert_file
+        self.certificate_key_file = opts.ssl_key_file
+        self.key_file_password = opts.ssl_key_pw
+        self.require_encryption = opts.require_encryption
+        self.ca_database = opts.ssl_cert_db
+
         if self.server:
             addr = self.server[0].rsplit(":", 1)
             self.host = addr[0]
@@ -55,14 +80,22 @@ class Options(object):
 
 
 class MailboxServer(object):
-    def __init__(self, host, port):
+    def __init__(self, host, port, require_encryption=False, certificate_file=None,
+                 certificate_key_file=None, key_file_password=None,
+                 ca_database=None):
         """ Initialize the server to wait on the given address for inbound
         connection requests.
         """
         self.host = host
         self.port = port
+        self.certificate_file = certificate_file
+        self.certificate_key_file = certificate_key_file
+        self.key_file_password = key_file_password
+        self.ca_database = ca_database
+        self.require_encryption = require_encryption
+
         self.mailboxes = {}
-        self.verbose = False
+        self.logging = False
         self.counter = 0
 
 
@@ -75,6 +108,13 @@ class MailboxServer(object):
         if self.listener is None:
             print("Error: could not listen on %s:%s" % (self.host, self.port))
             return False
+        # if self.certificate_file:
+        #     self.log("Setting SSL certificate %s" % self.certificate_file)
+        #     if not self.require_encryption:
+        #         self.log("Allowing both encrypted AND unencrypted connections!")
+        if self.certificate_file:
+            if not self.require_encryption:
+                self.log("Allowing both encrypted AND unencrypted connections!")
         return True
 
 
@@ -95,6 +135,26 @@ class MailboxServer(object):
             self.log("Accepting Connection.")
             cxtr = pn_listener_accept(l)
             pn_connector_set_context(cxtr, AUTHENTICATING)
+
+            # configure SSL
+            if self.certificate_file:
+                ssl_server = pn_connector_ssl(cxtr)
+                assert(ssl_server)
+                rc = pn_ssl_set_credentials(ssl_server,
+                                            self.certificate_file,
+                                            self.certificate_key_file,
+                                            self.key_file_password)
+                assert(rc == 0)
+                if not self.require_encryption:
+                    rc = pn_ssl_allow_unsecured_client(ssl_server)
+                    assert(rc == 0)
+
+                # TODO: client authentication incomplete, for now skip peer verification
+                rc = pn_ssl_set_peer_authentication(ssl_server,
+                                                    PN_SSL_NO_VERIFY_PEER,
+                                                    None)
+                assert(rc == 0)
+
             l = pn_driver_listener(self.driver)
 
 
@@ -345,7 +405,12 @@ class MailboxServer(object):
 def main():
     options = Options()
 
-    server = MailboxServer(options.host, options.port)
+    server = MailboxServer(options.host, options.port,
+                           options.require_encryption,
+                           options.certificate_file,
+                           options.certificate_key_file,
+                           options.key_file_password,
+                           options.ca_database)
     if (options.verbose):
         server.enableLogging()
 

Added: qpid/proton/branches/openssl/examples/mailbox/ssl-setup.sh
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/examples/mailbox/ssl-setup.sh?rev=1387642&view=auto
==============================================================================
--- qpid/proton/branches/openssl/examples/mailbox/ssl-setup.sh (added)
+++ qpid/proton/branches/openssl/examples/mailbox/ssl-setup.sh Wed Sep 19 15:32:50 2012
@@ -0,0 +1,30 @@
+#/bin/bash
+#
+#
+set -x
+
+# Step 0: create a password file
+
+echo "trustno1" > ./password.txt
+
+# Step 1: Create a self-signed certificate that identifies the CA
+
+openssl req -x509 -newkey rsa:2048 -keyout ca-private-key.pem -passout file:./password.txt -out ca-certificate.pem  -days 999 -subj "/O=Trust Me, Inc/CN=127.0.0.1"
+
+# Step 2: Create a certificate signing request for the server
+
+openssl req -newkey rsa:2048 -keyout server-private-key.pem -passout file:./password.txt -out server-request.pem -subj "/O=Soft Serve/CN=127.0.0.1"
+
+# Step 3: Use the "CA" to create a certificate for the server from the request:
+
+openssl x509 -req -in server-request.pem -CA ca-certificate.pem -CAkey ca-private-key.pem -CAcreateserial -passin file:./password.txt -days 999 -out server-certificate.pem
+
+# Step 4: create a certificate database to hold the "trusted" CA certificate
+
+mkdir ./trusted_db
+rm -f ./trusted_db/*
+mv ca-certificate.pem ./trusted_db
+c_rehash ./trusted_db
+
+
+

Propchange: qpid/proton/branches/openssl/examples/mailbox/ssl-setup.sh
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: qpid/proton/branches/openssl/proton-c/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/CMakeLists.txt?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/proton-c/CMakeLists.txt (original)
+++ qpid/proton/branches/openssl/proton-c/CMakeLists.txt Wed Sep 19 15:32:50 2012
@@ -5,6 +5,16 @@ project (Proton C)
 set (PN_VERSION_MAJOR 0)
 set (PN_VERSION_MINOR 1)
 
+include(CheckIncludeFile)
+CHECK_INCLUDE_FILE(openssl/ssl.h HAVE_OPENSSL_H)
+
+# Set the default SSL/TLS implementation
+set(ssl_impl, NONE)
+if (HAVE_OPENSSL_H)
+   set(ssl_impl openssl)
+endif(HAVE_OPENSSL_H)
+set(SSL_IMPL ${ssl_impl} CACHE STRING "Library to use for SSL/TLS support. Valid values: 'none','openssl'")
+
 configure_file (
   "${PROJECT_SOURCE_DIR}/pn_config.h.in"
   "${PROJECT_BINARY_DIR}/pn_config.h"
@@ -25,6 +35,14 @@ add_custom_command (
   DEPENDS ${PROJECT_SOURCE_DIR}/src/protocol.h.py
 )
 
+# Link in openssl if present
+if (SSL_IMPL STREQUAL openssl)
+  set (pn_driver_ssl_impl src/ssl/openssl.c)
+  set (SSL_LIB ssl crypto)
+else (SSL_IMPL STREQUAL openssl)
+  set (pn_driver_ssl_impl src/ssl/ssl_stub.c)
+endif (SSL_IMPL STREQUAL openssl)
+
 find_package(SWIG)
 if (SWIG_FOUND)
   add_subdirectory(bindings)
@@ -38,6 +56,7 @@ set (UUID_LIB uuid)
 
 set (qpid-proton-platform
   src/driver.c
+  ${pn_driver_ssl_impl}
 )
 
 add_library (
@@ -66,7 +85,7 @@ add_library (
   ${PROJECT_BINARY_DIR}/encodings.h
   ${PROJECT_BINARY_DIR}/protocol.h
 )
-target_link_libraries (qpid-proton ${UUID_LIB})
+target_link_libraries (qpid-proton ${UUID_LIB} ${SSL_LIB})
 
 add_executable (proton src/proton.c)
 target_link_libraries (proton qpid-proton)

Modified: qpid/proton/branches/openssl/proton-c/bindings/php/php.i
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/bindings/php/php.i?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/proton-c/bindings/php/php.i (original)
+++ qpid/proton/branches/openssl/proton-c/bindings/php/php.i Wed Sep 19 15:32:50 2012
@@ -10,6 +10,7 @@
 #include <proton/message.h>
 #include <proton/driver.h>
 #include <proton/messenger.h>
+#include <proton/ssl.h>
 
 #define zend_error_noreturn zend_error
 %}

Modified: qpid/proton/branches/openssl/proton-c/bindings/python/python.i
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/bindings/python/python.i?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/proton-c/bindings/python/python.i (original)
+++ qpid/proton/branches/openssl/proton-c/bindings/python/python.i Wed Sep 19 15:32:50 2012
@@ -6,6 +6,7 @@
 #include <proton/sasl.h>
 #include <proton/driver.h>
 #include <proton/messenger.h>
+#include <proton/ssl.h>  
 %}
 
 typedef unsigned int size_t;

Modified: qpid/proton/branches/openssl/proton-c/bindings/ruby/ruby.i
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/bindings/ruby/ruby.i?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/proton-c/bindings/ruby/ruby.i (original)
+++ qpid/proton/branches/openssl/proton-c/bindings/ruby/ruby.i Wed Sep 19 15:32:50 2012
@@ -6,6 +6,7 @@
 #include <proton/sasl.h>
 #include <proton/driver.h>
 #include <proton/messenger.h>
+#include <proton/ssl.h>
 %}
 
 typedef unsigned int size_t;

Modified: qpid/proton/branches/openssl/proton-c/include/proton/cproton.i
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/include/proton/cproton.i?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/proton-c/include/proton/cproton.i (original)
+++ qpid/proton/branches/openssl/proton-c/include/proton/cproton.i Wed Sep 19 15:32:50 2012
@@ -1281,3 +1281,8 @@
 
 
 %include "proton/messenger.h"
+
+
+
+%include "proton/ssl.h"
+

Modified: qpid/proton/branches/openssl/proton-c/include/proton/driver.h
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/include/proton/driver.h?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/proton-c/include/proton/driver.h (original)
+++ qpid/proton/branches/openssl/proton-c/include/proton/driver.h Wed Sep 19 15:32:50 2012
@@ -25,6 +25,7 @@
 #include <proton/error.h>
 #include <proton/engine.h>
 #include <proton/sasl.h>
+#include <proton/ssl.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -197,6 +198,8 @@ void pn_listener_close(pn_listener_t *li
 void pn_listener_free(pn_listener_t *listener);
 
 
+
+
 /** pn_connector - the client API **/
 
 /** Construct a connector to the given remote address.
@@ -265,7 +268,7 @@ pn_listener_t *pn_connector_listener(pn_
 
 /** Access the Authentication and Security context of the connector.
  *
- * @param[in] connector connector whose securty context will be
+ * @param[in] connector connector whose security context will be
  *                      returned
  * @return the Authentication and Security context for the connector,
  *         or NULL if none
@@ -306,6 +309,13 @@ void *pn_connector_context(pn_connector_
  */
 void pn_connector_set_context(pn_connector_t *connector, void *context);
 
+/** Access the SSL/TLS context of the connector.
+ *
+ * @param[in] connector connector whose SSL/TLS context will be returned
+ * @return the SSL/TLS context for the connector, or NULL if none
+ */
+pn_ssl_t *pn_connector_ssl(pn_connector_t *connector);
+
 /** Close the socket used by the connector.
  *
  * @param[in] connector the connector whose socket will be closed
@@ -327,6 +337,7 @@ bool pn_connector_closed(pn_connector_t 
  */
 void pn_connector_free(pn_connector_t *connector);
 
+
 #ifdef __cplusplus
 }
 #endif

Added: qpid/proton/branches/openssl/proton-c/include/proton/ssl.h
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/include/proton/ssl.h?rev=1387642&view=auto
==============================================================================
--- qpid/proton/branches/openssl/proton-c/include/proton/ssl.h (added)
+++ qpid/proton/branches/openssl/proton-c/include/proton/ssl.h Wed Sep 19 15:32:50 2012
@@ -0,0 +1,149 @@
+#ifndef PROTON_SSL_H
+#define PROTON_SSL_H 1
+
+/*
+ *
+ * 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 <sys/types.h>
+#include <stdbool.h>
+#include <proton/engine.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @file
+ * API for using SSL with the Transport Layer.
+ *
+ * A Transport may be configured to use SSL for encryption and/or authentication.  A
+ * Transport can be configured as either an "SSL client" or an "SSL server".  An SSL
+ * client is the party that proactively establishes a connection to an SSL server.  An SSL
+ * server is the party that accepts a connection request from a remote SSL client.
+ *
+ * If either an SSL server or client needs to identify itself with the remote node, it
+ * must have its SSL certificate configured (see ::pn_ssl_set_credentials()).
+ *
+ * If either an SSL server or client needs to verify the identity of the remote node, it
+ * must have its database of trusted CAs configured (see ::pn_ssl_set_trusted_ca_db()).
+ *
+ * An SSL server may allow peers to connect without SSL (eg. "in the clear"), see
+ * ::pn_ssl_allow_unsecured_client().
+ *
+ * The level of verification required of the remote may be configured (see
+ * ::pn_ssl_set_peer_authentication, ::pn_ssl_get_peer_authentication).
+ */
+
+typedef struct pn_ssl_t pn_ssl_t;
+
+/** Set the certificate that identifies the local node to the remote.
+ *
+ * This certificate establishes the identity for the local node.  It will be sent to the
+ * remote if the remote needs to verify the identity of this node.  This may be used for
+ * both SSL servers and SSL clients (if client authentication is required by the server).
+ *
+ * @param[in] ssl the ssl server/client will provide this certificate.
+ * @param[in] certificate_path path to file/database containing the identifying
+ * certificate.
+ * @param[in] private_key_path path to file/database containing the private key used to
+ * sign the certificate
+ * @param[in] password the password used to sign the key, else NULL if key is not
+ * protected.
+ * @return 0 on success
+ */
+ int pn_ssl_set_credentials( pn_ssl_t *ssl,
+                             const char *certificate_file,
+                             const char *private_key_file,
+                             const char *password);
+
+/** Configure the set of trusted CA certificates used by this node to verify peers.
+ *
+ * If the local SSL client/server needs to verify the identity of the remote, it must
+ * validate the signature of the remote's certificate.  This function sets the database of
+ * trusted CAs that will be used to verify the signature of the remote's certificate.
+ *
+ * @param[in] ssl the ssl server/client that will use the database.
+ * @param[in] certificate_db database of trusted CAs, used to authenticate the peer.
+ * @return 0 on success
+ */
+
+int pn_ssl_set_trusted_ca_db(pn_ssl_t *ssl,
+                             const char *certificate_db);
+
+/** Permit a server to accept connection requests from non-SSL clients.
+ *
+ * This configures the server to "sniff" the incoming client data stream, and dynamically
+ * determine whether SSL/TLS is being used.  This option is disabled by default: only
+ * clients using SSL/TLS are accepted.
+ *
+ * @param[in] ssl the SSL server that will accept the client connection.
+ * @return 0 on success
+ */
+int pn_ssl_allow_unsecured_client(pn_ssl_t *ssl);
+
+
+/** Determines the level of peer certificate validation. */
+typedef enum {
+  PN_SSL_VERIFY_PEER,     /**< require peer to provide a valid identifying certificate */
+  PN_SSL_NO_VERIFY_PEER,  /**< do not require peer to provide an identifying certificate */
+} pn_ssl_verify_mode_t;
+
+
+/** Configure the level of verification used on the peer certificate.
+ *
+ * This method controls how the peer's certificate is validated, if at all.  By default,
+ * SSL servers do not attempt to verify their peers (PN_SSL_NO_VERIFY), and SSL clients
+ * require the remote to provide a valid certificate (PN_SSL_VERIFY_PEER).
+ *
+ * @param[in] ssl the ssl client/server to configure.
+ * @param[in] mode the level of validation to apply to the peer's certificate.
+ * @param[in] trusted_CAs path to a database of trusted CAs that the server will advertise
+ * to the peer client if the server has been configured to verify its peer.
+ * @return 0 on success
+ */
+int pn_ssl_set_peer_authentication(pn_ssl_t *ssl,
+                                   const pn_ssl_verify_mode_t mode,
+                                   const char *trusted_CAs);
+
+/** Get the level of verification to be used on the peer certificate.
+ *
+ * Access the current peer certificate validation level.  See
+ * ::pn_ssl_set_peer_authentication().
+ *
+ *
+ * @param[in] ssl the ssl client/server to query.
+ * @param[out] mode the level of validation that will be applied to the peer's certificate.
+ * @param[out] trusted_CAs set to a buffer to hold the path to the database of trusted CAs
+ * that the server will advertise to the peer client. If NULL, the path will not be
+ * returned.
+ * @param[in,out] trusted_CAs_size on input set to the number of octets in trusted_CAs.
+ * on output, set to the number of octets needed to hold the value of trusted_CAs plus a
+ * null byte.  @return 0 on success
+ */
+int pn_ssl_get_peer_authentication(pn_ssl_t *ssl,
+                                   pn_ssl_verify_mode_t *mode,
+                                   char *trusted_CAs, size_t *trusted_CAs_size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ssl.h */

Propchange: qpid/proton/branches/openssl/proton-c/include/proton/ssl.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: qpid/proton/branches/openssl/proton-c/pn_config.h.in
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/pn_config.h.in?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/proton-c/pn_config.h.in (original)
+++ qpid/proton/branches/openssl/proton-c/pn_config.h.in Wed Sep 19 15:32:50 2012
@@ -25,4 +25,6 @@
 #define PN_VERSION_MAJOR @PN_VERSION_MAJOR@
 #define PN_VERSION_MINOR @PN_VERSION_MINOR@
 
+#cmakedefine HAVE_OPENSSL_H 1
+
 #endif /* pn_config.h */

Modified: qpid/proton/branches/openssl/proton-c/src/driver.c
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/src/driver.c?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/proton-c/src/driver.c (original)
+++ qpid/proton/branches/openssl/proton-c/src/driver.c Wed Sep 19 15:32:50 2012
@@ -33,8 +33,9 @@
 #include <proton/driver.h>
 #include <proton/error.h>
 #include <proton/sasl.h>
+#include <proton/ssl.h>
 #include "util.h"
-
+#include "ssl/ssl-internal.h"
 
 /* Decls */
 
@@ -391,6 +392,17 @@ pn_sasl_t *pn_connector_sasl(pn_connecto
   return ctor ? ctor->sasl : NULL;
 }
 
+pn_ssl_t *pn_connector_ssl(pn_connector_t *ctor)
+{
+  if (ctor) {
+    // use server mode SSL if this connector was created by a listener
+    if (ctor->listener)
+      return pn_ssl_server(ctor->transport);
+    return pn_ssl_client(ctor->transport);
+  }
+  return NULL;
+}
+
 void pn_connector_set_connection(pn_connector_t *ctor, pn_connection_t *connection)
 {
   if (!ctor) return;

Modified: qpid/proton/branches/openssl/proton-c/src/engine/engine-internal.h
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/src/engine/engine-internal.h?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/proton-c/src/engine/engine-internal.h (original)
+++ qpid/proton/branches/openssl/proton-c/src/engine/engine-internal.h Wed Sep 19 15:32:50 2012
@@ -87,12 +87,14 @@ typedef struct {
 #define SCRATCH (1024)
 
 #include <proton/sasl.h>
+#include <proton/ssl.h>
 
 struct pn_transport_t {
   ssize_t (*process_input)(pn_transport_t *, char *, size_t);
   ssize_t (*process_output)(pn_transport_t *, char *, size_t);
   size_t header_count;
   pn_sasl_t *sasl;
+  pn_ssl_t *ssl;
   pn_connection_t *connection;
   pn_dispatcher_t *disp;
   bool open_sent;

Modified: qpid/proton/branches/openssl/proton-c/src/engine/engine.c
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/src/engine/engine.c?rev=1387642&r1=1387641&r2=1387642&view=diff
==============================================================================
--- qpid/proton/branches/openssl/proton-c/src/engine/engine.c (original)
+++ qpid/proton/branches/openssl/proton-c/src/engine/engine.c Wed Sep 19 15:32:50 2012
@@ -30,6 +30,7 @@
 #include <stdio.h>
 
 #include "../sasl/sasl-internal.h"
+#include "../ssl/ssl-internal.h"
 
 // delivery buffers
 
@@ -229,6 +230,7 @@ void pn_transport_free(pn_transport_t *t
 {
   if (!transport) return;
 
+  pn_ssl_free(transport->ssl);
   pn_sasl_free(transport->sasl);
   pn_dispatcher_free(transport->disp);
   for (int i = 0; i < transport->session_capacity; i++) {
@@ -702,6 +704,7 @@ void pn_transport_init(pn_transport_t *t
   transport->process_output = pn_output_write_amqp_header;
   transport->header_count = 0;
   transport->sasl = NULL;
+  transport->ssl = NULL;
   transport->disp = pn_dispatcher(0, transport);
 
   pn_dispatcher_action(transport->disp, OPEN, "OPEN", pn_do_open);
@@ -1463,8 +1466,13 @@ ssize_t pn_input(pn_transport_t *transpo
 
   size_t consumed = 0;
 
+  const bool use_ssl = transport->ssl != NULL;
   while (true) {
-    ssize_t n = transport->process_input(transport, bytes + consumed, available - consumed);
+    ssize_t n;
+    if (use_ssl)
+      n = pn_ssl_input( transport->ssl, bytes + consumed, available - consumed);
+    else
+      n = transport->process_input(transport, bytes + consumed, available - consumed);
     if (n > 0) {
       consumed += n;
       if (consumed >= available) {
@@ -2025,8 +2033,14 @@ ssize_t pn_output(pn_transport_t *transp
 
   size_t total = 0;
 
+  const bool use_ssl = transport->ssl != NULL;
+
   while (size - total > 0) {
-    ssize_t n = transport->process_output(transport, bytes + total, size - total);
+    ssize_t n;
+    if (use_ssl)
+      n = pn_ssl_output( transport->ssl, bytes + total, size - total);
+    else
+      n = transport->process_output(transport, bytes + total, size - total);
     if (n > 0) {
       total += n;
     } else if (n == 0) {
@@ -2053,6 +2067,7 @@ ssize_t pn_output(pn_transport_t *transp
 void pn_trace(pn_transport_t *transport, pn_trace_t trace)
 {
   if (transport->sasl) pn_sasl_trace(transport->sasl, trace);
+  if (transport->ssl) pn_ssl_trace(transport->ssl, trace);
   transport->disp->trace = trace;
 }
 

Added: qpid/proton/branches/openssl/proton-c/src/ssl/openssl.c
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/src/ssl/openssl.c?rev=1387642&view=auto
==============================================================================
--- qpid/proton/branches/openssl/proton-c/src/ssl/openssl.c (added)
+++ qpid/proton/branches/openssl/proton-c/src/ssl/openssl.c Wed Sep 19 15:32:50 2012
@@ -0,0 +1,829 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#define _POSIX_C_SOURCE 1
+
+#include <proton/ssl.h>
+#include "./ssl-internal.h"
+#include <proton/engine.h>
+#include "../engine/engine-internal.h"
+#include "../util.h"
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+
+
+/** @file
+ * SSL/TLS support API.
+ *
+ * This file contains an OpenSSL-based implemention of the SSL/TLS API.
+ */
+
+static int ssl_initialized;
+
+typedef enum { SSL_MODE_CLIENT, SSL_MODE_SERVER } ssl_mode_t;
+typedef enum { UNKNOWN_CONNECTION, SSL_CONNECTION, CLEAR_CONNECTION } connection_mode_t;
+
+struct pn_ssl_t {
+  SSL_CTX *ctx;
+  SSL *ssl;
+  ssl_mode_t mode;
+  bool allow_unsecured;
+  bool ca_db;           // true when CA database configured
+  char *keyfile_pw;
+  pn_ssl_verify_mode_t verify_mode;    // NEED INIT
+  char *trusted_CAs;
+
+  pn_transport_t *transport;
+
+  BIO *bio_ssl;         // i/o from/to SSL socket layer
+  BIO *bio_ssl_io;      // SSL "half" of network-facing BIO
+  BIO *bio_net_io;      // socket-side "half" of network-facing BIO
+  bool read_stalled;  // SSL has data to read, but client buffer is full.
+  bool ssl_shutdown;    // BIO_ssl_shutdown() called on socket.
+  ssize_t app_closed;   // error code returned by upper layer on close
+  ssize_t ssl_closed;   // SSL socket has closed (use upper layer code)
+
+  bool read_blocked;    // SSL blocked until more network data is read
+  bool write_blocked;   // SSL blocked until data is written to network
+  
+  // buffers for holding I/O from "applications" above SSL
+#define APP_BUF_SIZE    (4*1024)
+  char outbuf[APP_BUF_SIZE];
+  size_t out_count;
+  char inbuf[APP_BUF_SIZE];
+  size_t in_count;
+
+  // process cleartext i/o "above" the SSL layer
+  ssize_t (*process_input)(pn_transport_t *, char *, size_t);
+  ssize_t (*process_output)(pn_transport_t *, char *, size_t);
+
+  pn_trace_t trace;
+};
+
+
+/* */
+static int keyfile_pw_cb(char *buf, int size, int rwflag, void *userdata);
+static ssize_t process_input_ssl( pn_transport_t *transport, char *input_data, size_t len);
+static ssize_t process_output_ssl( pn_transport_t *transport, char *input_data, size_t len);
+static ssize_t process_input_cleartext(pn_transport_t *transport, char *input_data, size_t len);
+static ssize_t process_output_cleartext(pn_transport_t *transport, char *buffer, size_t max_len);
+static ssize_t process_input_unknown(pn_transport_t *transport, char *input_data, size_t len);
+static ssize_t process_output_unknown(pn_transport_t *transport, char *input_data, size_t len);
+static connection_mode_t check_for_ssl_connection( const char *data, size_t len );
+static int init_ssl_socket( pn_ssl_t * );
+
+
+// @todo: used to avoid littering the code with calls to printf...
+static void _log_error(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+}
+
+// @todo: used to avoid littering the code with calls to printf...
+static void _log(pn_ssl_t *ssl, const char *fmt, ...)
+{
+  if (PN_TRACE_DRV & ssl->trace) {
+    va_list ap;
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+  }
+}
+
+
+// @todo replace with a "reasonable" default (?), allow application to register its own
+// callback.
+#if 0
+static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
+{
+    fprintf(stderr, "VERIFY_CALLBACK: pre-verify-ok=%d\n", preverify_ok);
+
+           char    buf[256];
+           X509   *err_cert;
+           int     err, depth;
+
+           err_cert = X509_STORE_CTX_get_current_cert(ctx);
+           err = X509_STORE_CTX_get_error(ctx);
+           depth = X509_STORE_CTX_get_error_depth(ctx);
+
+           /*
+            * Retrieve the pointer to the SSL of the connection currently treated
+            * and the application specific data stored into the SSL object.
+            */
+
+           X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
+
+           /*
+            * Catch a too long certificate chain. The depth limit set using
+            * SSL_CTX_set_verify_depth() is by purpose set to "limit+1" so
+            * that whenever the "depth>verify_depth" condition is met, we
+            * have violated the limit and want to log this error condition.
+            * We must do it here, because the CHAIN_TOO_LONG error would not
+            * be found explicitly; only errors introduced by cutting off the
+            * additional certificates would be logged.
+            */
+           if (!preverify_ok) {
+               printf("verify error:num=%d:%s:depth=%d:%s\n", err,
+                        X509_verify_cert_error_string(err), depth, buf);
+           }
+
+           /*
+            * At this point, err contains the last verification error. We can use
+            * it for something special
+            */
+           if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
+           {
+             X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
+             printf("issuer= %s\n", buf);
+           }
+
+    return 1;
+}
+#endif
+
+
+
+
+/** Public API - visible to application code */
+
+
+int pn_ssl_set_credentials( pn_ssl_t *ssl,
+                            const char *certificate_file,
+                            const char *private_key_file,
+                            const char *password)
+{
+  if (!ssl) return 0;
+  if (ssl->ssl) {
+    _log_error("Error: attempting to set credentials after SSL connection initialized.\n");
+    return -1;
+  }
+
+  if (SSL_CTX_use_certificate_chain_file(ssl->ctx, certificate_file) != 1) {
+    _log_error("SSL_CTX_use_certificate_chain_file( %s ) failed\n", certificate_file);
+    return -3;
+  }
+
+  if (password) {
+    ssl->keyfile_pw = pn_strdup(password);  // @todo: obfuscate me!!!
+    SSL_CTX_set_default_passwd_cb(ssl->ctx, keyfile_pw_cb);
+    SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ssl->keyfile_pw);
+  }
+
+  if (SSL_CTX_use_PrivateKey_file(ssl->ctx, private_key_file, SSL_FILETYPE_PEM) != 1) {
+    _log_error("SSL_CTX_use_PrivateKey_file( %s ) failed\n", private_key_file);
+    return -4;
+  }
+
+  _log( ssl, "Configured local certificate file %s\n", certificate_file );
+  return 0;
+}
+
+
+int pn_ssl_set_trusted_ca_db(pn_ssl_t *ssl,
+                             const char *certificate_db)
+{
+  if (!ssl) return 0;
+  if (ssl->ssl) {
+    _log_error("Error: attempting to set trusted CA db after SSL connection initialized.\n");
+    return -1;
+  }
+
+  // certificates can be either a file or a directory, which determines how it is passed
+  // to SSL_CTX_load_verify_locations()
+  struct stat sbuf;
+  if (stat( certificate_db, &sbuf ) != 0) {
+    _log_error("stat(%s) failed: %s\n", certificate_db, strerror(errno));
+    return -1;
+  }
+
+  const char *file;
+  const char *dir;
+  if (S_ISDIR(sbuf.st_mode)) {
+    dir = certificate_db;
+    file = NULL;
+  } else {
+    dir = NULL;
+    file = certificate_db;
+  }
+
+  if (SSL_CTX_load_verify_locations( ssl->ctx, file, dir ) != 1) {
+    _log_error("SSL_CTX_load_verify_locations( %s ) failed\n", certificate_db);
+    return -1;
+  }
+
+  _log( ssl, "loaded trusted CA database: file=%s dir=%s\n", file, dir );
+  return 0;
+}
+
+
+int pn_ssl_allow_unsecured_client(pn_ssl_t *ssl)
+{
+  if (ssl) {
+    if (ssl->mode != SSL_MODE_SERVER) {
+      _log_error("Cannot permit unsecured clients - not a server.\n");
+      return -1;
+    }
+    ssl->allow_unsecured = true;
+    ssl->process_input = process_input_unknown;
+    ssl->process_output = process_output_unknown;
+    _log( ssl, "Allowing connections from unsecured clients.\n" );
+  }
+  return 0;
+}
+
+
+int pn_ssl_set_peer_authentication(pn_ssl_t *ssl,
+                                   const pn_ssl_verify_mode_t mode,
+                                   const char *trusted_CAs)
+{
+  if (!ssl) return 0;
+  if (ssl->ssl) {
+    _log_error("Error: attempting to set peer authentication after SSL connection initialized.\n");
+    return -1;
+  }
+
+  switch (mode) {
+  case PN_SSL_VERIFY_PEER:
+
+    if (ssl->mode == SSL_MODE_SERVER) {
+      // openssl requires that server connections supply a list of trusted CAs which is
+      // sent to the client
+      if (!trusted_CAs) {
+        _log_error("Error: a list of trusted CAs must be provided.\n");
+        return -1;
+      }
+
+      ssl->trusted_CAs = pn_strdup( trusted_CAs );
+      STACK_OF(X509_NAME) *cert_names;
+      cert_names = SSL_load_client_CA_file( ssl->trusted_CAs );
+      if (cert_names != NULL)
+        SSL_CTX_set_client_CA_list(ssl->ctx, cert_names);
+      else {
+        _log_error("Unable to process file of trusted CAs: %s\n", trusted_CAs);
+        return -1;
+      }
+    }
+
+    SSL_CTX_set_verify( ssl->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
+    // verify_callback /*?verify callback?*/ );
+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+    SSL_CTX_set_verify_depth(ssl->ctx, 1);
+#endif
+    ssl->verify_mode = PN_SSL_VERIFY_PEER;
+    break;
+
+  case PN_SSL_NO_VERIFY_PEER:
+    SSL_CTX_set_verify( ssl->ctx, SSL_VERIFY_NONE, NULL );
+    ssl->verify_mode = PN_SSL_NO_VERIFY_PEER;
+    break;
+
+  default:
+    _log_error( "Invalid peer authentication mode given.\n" );
+    return -1;
+  }
+
+    _log( ssl, "Peer authentication mode set to %s\n", (ssl->verify_mode == PN_SSL_VERIFY_PEER) ? "VERIFY-PEER" : "NO-VERIFY-PEER");
+    return 0;
+}
+
+
+int pn_ssl_get_peer_authentication(pn_ssl_t *ssl,
+                                   pn_ssl_verify_mode_t *mode,
+                                   char *trusted_CAs, size_t *trusted_CAs_size)
+{
+  if (!ssl) return -1;
+
+  if (mode) *mode = ssl->verify_mode;
+  if (trusted_CAs && trusted_CAs_size && *trusted_CAs_size) {
+    if (ssl->trusted_CAs) {
+      strncpy( trusted_CAs, ssl->trusted_CAs, *trusted_CAs_size );
+      trusted_CAs[*trusted_CAs_size - 1] = '\0';
+      *trusted_CAs_size = strlen(ssl->trusted_CAs) + 1;
+    } else {
+      *trusted_CAs = '\0';
+      *trusted_CAs_size = 0;
+    }
+  } else if (trusted_CAs_size) {
+    *trusted_CAs_size = (ssl->trusted_CAs) ? strlen(ssl->trusted_CAs) + 1 : 0;
+  }
+  return 0;
+}
+
+
+pn_ssl_t *pn_ssl_server(pn_transport_t *transport)
+{
+  if (!transport) return NULL;
+  if (transport->ssl) {
+    if (transport->ssl->mode != SSL_MODE_SERVER) {
+      _log_error("Error: transport already configured as a client.\n");
+      return NULL;
+    }
+    return transport->ssl;
+  }
+
+  if (!ssl_initialized) {
+    ssl_initialized = 1;
+    SSL_library_init();
+    SSL_load_error_strings();
+  }
+
+  pn_ssl_t *ssl = calloc(1, sizeof(pn_ssl_t));
+  if (!ssl) return NULL;
+
+  ssl->ctx = SSL_CTX_new(SSLv23_server_method());
+  if (!ssl->ctx) {
+    _log_error("Unable to initialize SSL context: %s\n", strerror(errno));
+    free(ssl);
+    return NULL;
+  }
+  ssl->verify_mode = PN_SSL_NO_VERIFY_PEER;
+  SSL_CTX_set_verify( ssl->ctx, SSL_VERIFY_NONE, NULL );        // default: no client authentication
+
+  ssl->mode = SSL_MODE_SERVER;
+  ssl->transport = transport;
+  ssl->process_input = process_input_ssl;
+  ssl->process_output = process_output_ssl;
+  transport->ssl = ssl;
+
+  ssl->trace = PN_TRACE_OFF;
+
+  _log( ssl, "Setting up Server SSL connection.\n" );
+  return ssl;
+}
+
+pn_ssl_t *pn_ssl_client(pn_transport_t *transport)
+{
+  if (!transport) return NULL;
+  if (transport->ssl) {
+    if (transport->ssl->mode != SSL_MODE_CLIENT) {
+      _log_error("Error: transport already configured as a server.\n");
+      return NULL;
+    }
+    return transport->ssl;
+  }
+
+  if (!ssl_initialized) {
+    ssl_initialized = 1;
+    SSL_library_init();
+    SSL_load_error_strings();
+  }
+
+  pn_ssl_t *ssl = calloc(1, sizeof(pn_ssl_t));
+  if (!ssl) return NULL;
+
+  ssl->ctx = SSL_CTX_new(SSLv23_client_method());
+  if (!ssl->ctx) {
+    _log_error("Unable to initialize SSL context: %s\n", strerror(errno));
+    free(ssl);
+    return NULL;
+  }
+  ssl->verify_mode = PN_SSL_VERIFY_PEER;
+  SSL_CTX_set_verify( ssl->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL );
+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+  SSL_CTX_set_verify_depth(ssl->ctx, 1);
+#endif
+
+  ssl->mode = SSL_MODE_CLIENT;
+
+  ssl->transport = transport;
+  ssl->process_input = process_input_ssl;
+  ssl->process_output = process_output_ssl;
+  transport->ssl = ssl;
+
+  ssl->trace = PN_TRACE_OFF;
+
+  _log( ssl, "Setting up Client SSL connection.\n" );
+  return ssl;
+}
+
+void pn_ssl_free( pn_ssl_t *ssl)
+{
+  if (!ssl) return;
+  _log( ssl, "SSL socket freed.\n" );
+  if (ssl->bio_ssl) BIO_free(ssl->bio_ssl);
+  if (ssl->ssl) SSL_free(ssl->ssl);
+  else {
+    if (ssl->bio_ssl_io) BIO_free(ssl->bio_ssl_io);
+    if (ssl->bio_net_io) BIO_free(ssl->bio_net_io);
+  }
+  if (ssl->ctx) SSL_CTX_free(ssl->ctx);
+
+  if (ssl->keyfile_pw) free(ssl->keyfile_pw);
+  if (ssl->trusted_CAs) free(ssl->trusted_CAs);
+
+  free(ssl);
+}
+
+// move data received from the network into the SSL layer
+ssize_t pn_ssl_input(pn_ssl_t *ssl, char *bytes, size_t available)
+{
+  return ssl->process_input( ssl->transport, bytes, available );
+}
+
+// pull output from the SSL layer and move into network output buffers
+ssize_t pn_ssl_output(pn_ssl_t *ssl, char *buffer, size_t max_size)
+{
+  return ssl->process_output( ssl->transport, buffer, max_size );
+}
+
+
+/** Private: */
+
+static int keyfile_pw_cb(char *buf, int size, int rwflag, void *userdata)
+{
+    strncpy(buf, (char *)userdata, size);   // @todo: un-obfuscate me!!!
+    buf[size - 1] = '\0';
+    return(strlen(buf));
+}
+
+
+int start_ssl_shutdown( pn_ssl_t *ssl )
+{
+  if (!ssl->ssl_shutdown) {
+    _log(ssl, "Shutting down SSL connection...\n");
+    ssl->ssl_shutdown = true;
+    BIO_ssl_shutdown( ssl->bio_ssl );
+  }
+  return 0;
+}
+
+
+
+static int setup_ssl_connection( pn_ssl_t *ssl )
+{
+  _log( ssl, "SSL connection detected.\n");
+  ssl->process_input = process_input_ssl;
+  ssl->process_output = process_output_ssl;
+  return 0;
+}
+
+//////// SSL Connections
+
+
+// take data from the network, and pass it into SSL.  Attempt to read decrypted data from
+// SSL socket and pass it to the application.
+static ssize_t process_input_ssl( pn_transport_t *transport, char *input_data, size_t available)
+{
+  pn_ssl_t *ssl = transport->ssl;
+  if (!ssl) return PN_ERR;
+  if (ssl->ssl == NULL && init_ssl_socket(ssl)) return PN_ERR;
+
+  /* if (ssl->write_blocked) { */
+  /*   _log(ssl, "SSL write_blocked, ignoring input data\n" ); */
+  /*   return 0; */
+  /* } */
+
+  ssize_t consumed = 0;
+
+  // Write to network bio as much as possible, consuming bytes/available
+
+  if (available) {
+    int written = BIO_write( ssl->bio_net_io, input_data, available );
+    if (written > 0) {
+      input_data += written;
+      available -= written;
+      consumed += written;
+      ssl->read_blocked = false;
+      _log( ssl, "Wrote %d bytes to BIO Layer, %d left over\n", written, available );
+    }
+  }
+
+  // process any work available at the SSL socket
+
+  if (!ssl->ssl_closed) {
+    int pending = BIO_pending(ssl->bio_ssl);
+    int available = pn_min( (APP_BUF_SIZE - ssl->in_count), pending );
+    while (available > 0) {
+      int written = BIO_read( ssl->bio_ssl, &ssl->inbuf[ssl->in_count], available );
+      if (written > 0) {
+        ssl->in_count += written;
+        _log( ssl, "Read %d bytes from socket for app\n", written );
+      } else {
+        if (!BIO_should_retry(ssl->bio_ssl)) {
+          _log(ssl, "Read from SSL socket failed - SSL connection closed!!\n");
+          ssl->ssl_closed = (ssl->app_closed) ? ssl->app_closed : PN_EOS;
+          start_ssl_shutdown(ssl);
+        } else {
+          if (BIO_should_write( ssl->bio_ssl )) {
+            ssl->write_blocked = true;
+            _log(ssl, "Detected write-blocked\n");
+          }
+          if (BIO_should_read( ssl->bio_ssl )) {
+            ssl->read_blocked = true;
+            _log(ssl, "Detected read-blocked\n");
+          }
+        }
+        break;
+      }
+      pending = BIO_pending(ssl->bio_ssl);
+      available = pn_min( (APP_BUF_SIZE - ssl->in_count), pending );
+    }
+  }
+
+  // write incoming data to app layer
+
+  if (ssl->app_closed) {
+    ssl->in_count = 0;        // cannot accept more input, drop it
+  } else {
+    char *data = ssl->inbuf;
+    while (ssl->in_count > 0) {
+      ssize_t consumed = transport->process_input(transport, data, ssl->in_count);
+      if (consumed > 0) {
+        ssl->in_count -= consumed;
+        data += consumed;
+        _log( ssl, "Application consumed %d bytes from peer\n", (int) consumed );
+      } else {
+        if (consumed < 0) {
+          _log(ssl, "Application layer closed: %d (in_count=%d)\n", (int) consumed, (int)ssl->in_count);
+          ssl->app_closed = consumed;
+          if (consumed == PN_EOS) {
+            if (transport->disp->trace & (PN_TRACE_RAW | PN_TRACE_FRM))
+              pn_dispatcher_trace(transport->disp, 0, "<- EOS\n");
+          } else {
+            pn_dispatcher_trace(transport->disp, 0, "ERROR[%i] %s\n",
+                                pn_error_code(transport->error),
+                                pn_error_text(transport->error));
+          }
+        }
+        break;
+      }
+    }
+    if (!ssl->app_closed && ssl->in_count > 0 && data != ssl->inbuf)
+      memmove( ssl->inbuf, data, ssl->in_count );
+  }
+
+  //if (consumed == 0 && ssl->ssl_closed) {
+  if (ssl->ssl_closed) {
+    consumed = ssl->app_closed;
+  }
+
+  _log(ssl, "process_input_ssl() returning %d\n", (int) consumed);
+  return consumed;
+}
+
+static ssize_t process_output_ssl( pn_transport_t *transport, char *buffer, size_t max_len)
+{
+  pn_ssl_t *ssl = transport->ssl;
+  if (!ssl) return PN_ERR;
+  if (ssl->ssl == NULL && init_ssl_socket(ssl)) return PN_ERR;
+
+  /* if (ssl->read_blocked) { */
+  /*   _log(ssl, "SSL read_blocked, skipping output data\n" ); */
+  /*   return 0; */
+  /* } */
+
+  ssize_t written = 0;
+
+  // first, get any pending application output, if possible
+
+  if (!ssl->app_closed) {
+    while (ssl->out_count < APP_BUF_SIZE) {
+      ssize_t app_bytes = transport->process_output(transport, &ssl->outbuf[ssl->out_count], APP_BUF_SIZE - ssl->out_count);
+      if (app_bytes > 0) {
+        ssl->out_count += app_bytes;
+        _log( ssl, "Gathered %d bytes from app to send to peer\n", app_bytes );
+      } else {
+        if (app_bytes < 0) {
+          _log(ssl, "Application layer closed: %d (out_count=%d)\n", (int) app_bytes, (int) ssl->out_count);
+          ssl->app_closed = app_bytes;
+          if (app_bytes == PN_EOS) {
+            if (transport->disp->trace & (PN_TRACE_RAW | PN_TRACE_FRM))
+              pn_dispatcher_trace(transport->disp, 0, "-> EOS\n");
+          } else {
+            if (transport->disp->trace & (PN_TRACE_RAW | PN_TRACE_FRM))
+              pn_dispatcher_trace(transport->disp, 0, "-> EOS (%zi) %s\n", app_bytes,
+                                  pn_error_text(transport->error));
+          }
+        }
+        break;
+      }
+    }
+  }
+
+  // now push any pending app data into the socket
+
+  if (ssl->ssl_closed) {
+    ssl->out_count = 0;       // cannot write to socket, so erase app output data
+  } else {
+    char *data = ssl->outbuf;
+    while (ssl->out_count > 0) {
+      int written = BIO_write( ssl->bio_ssl, data, ssl->out_count );
+      if (written > 0) {
+        data += written;
+        ssl->out_count -= written;
+        _log( ssl, "Wrote %d bytes from app to socket\n", written );
+      } else {
+        if (!BIO_should_retry(ssl->bio_ssl)) {
+          _log(ssl, "Write to SSL socket failed - SSL connection closed!!\n");
+          ssl->ssl_closed = (ssl->app_closed) ? ssl->app_closed : PN_EOS;
+          start_ssl_shutdown(ssl);
+        } else {
+          if (BIO_should_read( ssl->bio_ssl )) {
+            ssl->read_blocked = true;
+            _log(ssl, "Detected read-blocked\n");
+          }
+          if (BIO_should_write( ssl->bio_ssl )) {
+            ssl->write_blocked = true;
+            _log(ssl, "Detected write-blocked\n");
+          }
+        }
+        break;
+      }
+    }
+
+    if (ssl->out_count == 0) {
+      if (ssl->app_closed) start_ssl_shutdown(ssl);
+    } else if (data != ssl->outbuf) {
+      memmove( ssl->outbuf, data, ssl->out_count );
+    }
+  }
+
+  // read from the network bio as much as possible, filling the buffer
+  if (max_len) {
+    int available = BIO_read( ssl->bio_net_io, buffer, max_len );
+    if (available > 0) {
+      max_len -= available;
+      buffer += available;
+      written += available;
+      ssl->write_blocked = false;
+      _log( ssl, "Read %d bytes from BIO Layer\n", available );
+    }
+  }
+
+  // once the app closes, and we drain any data it has written, we can shutdown the SSL
+  // connection cleanly.
+
+  if (written == 0 && ssl->ssl_closed && BIO_pending(ssl->bio_net_io) == 0) {
+    written = ssl->ssl_closed;
+  }
+  _log(ssl, "process_output_ssl() returning %d\n", (int) written);
+  return written;
+}
+
+static int init_ssl_socket( pn_ssl_t *ssl )
+{
+  if (ssl->ssl) return 0;
+
+  ssl->ssl = SSL_new(ssl->ctx);
+  if (!ssl->ssl) {
+    _log_error( "SSL socket setup failure.\n" );
+    return -1;
+  }
+
+  // now layer a BIO over the SSL socket
+  ssl->bio_ssl = BIO_new(BIO_f_ssl());
+  if (!ssl->bio_ssl) {
+    _log_error( "BIO setup failure.\n" );
+    return -1;
+  }
+  (void)BIO_set_ssl(ssl->bio_ssl, ssl->ssl, BIO_NOCLOSE);
+
+  // create the "lower" BIO "pipe", and attach it below the SSL layer
+  if (!BIO_new_bio_pair(&ssl->bio_ssl_io, 0, &ssl->bio_net_io, 0)) {
+    _log_error( "BIO setup failure.\n" );
+    return -1;
+  }
+  SSL_set_bio(ssl->ssl, ssl->bio_ssl_io, ssl->bio_ssl_io);
+
+  if (ssl->mode == SSL_MODE_SERVER) {
+    SSL_set_accept_state(ssl->ssl);
+    BIO_set_ssl_mode(ssl->bio_ssl, 0);  // server mode
+    _log( ssl, "Server SSL socket created.\n" );
+  } else {      // client mode
+    SSL_set_connect_state(ssl->ssl);
+    BIO_set_ssl_mode(ssl->bio_ssl, 1);  // client mode
+    _log( ssl, "Client SSL socket created.\n" );
+  }
+  return 0;
+}
+
+//////// CLEARTEXT CONNECTIONS
+
+static ssize_t process_input_cleartext(pn_transport_t *transport, char *input_data, size_t len)
+{
+  // just write directly to layer "above" SSL
+  return transport->process_input( transport, input_data, len );
+}
+
+static ssize_t process_output_cleartext(pn_transport_t *transport, char *buffer, size_t max_len)
+{
+  // just read directly from the layer "above" SSL
+  return transport->process_output( transport, buffer, max_len );
+}
+
+
+
+static int setup_cleartext_connection( pn_ssl_t *ssl )
+{
+  _log( ssl, "Cleartext connection detected.\n");
+  ssl->process_input = process_input_cleartext;
+  ssl->process_output = process_output_cleartext;
+  return 0;
+}
+
+
+// until we determine if the client is using SSL or not:
+
+static ssize_t process_input_unknown(pn_transport_t *transport, char *input_data, size_t len)
+{
+  switch (check_for_ssl_connection( input_data, len )) {
+  case SSL_CONNECTION:
+    setup_ssl_connection( transport->ssl );
+    return transport->ssl->process_input( transport, input_data, len );
+  case CLEAR_CONNECTION:
+    setup_cleartext_connection( transport->ssl );
+    return transport->ssl->process_input( transport, input_data, len );
+  default:
+    return 0;
+  }
+}
+
+static ssize_t process_output_unknown(pn_transport_t *transport, char *input_data, size_t len)
+{
+  // do not do output until we know if SSL is used or not
+  return 0;
+}
+
+static connection_mode_t check_for_ssl_connection( const char *data, size_t len )
+{
+  if (len >= 5) {
+    const unsigned char *buf = (unsigned char *)data;
+    /*
+     * SSLv2 Client Hello format
+     * http://www.mozilla.org/projects/security/pki/nss/ssl/draft02.html
+     *
+     * Bytes 0-1: RECORD-LENGTH
+     * Byte    2: MSG-CLIENT-HELLO (1)
+     * Byte    3: CLIENT-VERSION-MSB
+     * Byte    4: CLIENT-VERSION-LSB
+     *
+     * Allowed versions:
+     * 2.0 - SSLv2
+     * 3.0 - SSLv3
+     * 3.1 - TLS 1.0
+     * 3.2 - TLS 1.1
+     * 3.3 - TLS 1.2
+     *
+     * The version sent in the Client-Hello is the latest version supported by
+     * the client. NSS may send version 3.x in an SSLv2 header for
+     * maximum compatibility.
+     */
+    int isSSL2Handshake = buf[2] == 1 &&   // MSG-CLIENT-HELLO
+      ((buf[3] == 3 && buf[4] <= 3) ||    // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
+       (buf[3] == 2 && buf[4] == 0));     // SSL 2
+
+    /*
+     * SSLv3/TLS Client Hello format
+     * RFC 2246
+     *
+     * Byte    0: ContentType (handshake - 22)
+     * Bytes 1-2: ProtocolVersion {major, minor}
+     *
+     * Allowed versions:
+     * 3.0 - SSLv3
+     * 3.1 - TLS 1.0
+     * 3.2 - TLS 1.1
+     * 3.3 - TLS 1.2
+     */
+    int isSSL3Handshake = buf[0] == 22 &&  // handshake
+      (buf[1] == 3 && buf[2] <= 3);       // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
+
+    if (isSSL2Handshake || isSSL3Handshake) {
+      return SSL_CONNECTION;
+    } else {
+      return CLEAR_CONNECTION;
+    }
+  }
+  return UNKNOWN_CONNECTION;
+}
+
+void pn_ssl_trace(pn_ssl_t *ssl, pn_trace_t trace)
+{
+  ssl->trace = trace;
+}

Propchange: qpid/proton/branches/openssl/proton-c/src/ssl/openssl.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: qpid/proton/branches/openssl/proton-c/src/ssl/ssl-internal.h
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/src/ssl/ssl-internal.h?rev=1387642&view=auto
==============================================================================
--- qpid/proton/branches/openssl/proton-c/src/ssl/ssl-internal.h (added)
+++ qpid/proton/branches/openssl/proton-c/src/ssl/ssl-internal.h Wed Sep 19 15:32:50 2012
@@ -0,0 +1,92 @@
+#ifndef PROTON_SSL_INTERNAL_H
+#define PROTON_SSL_INTERNAL_H 1
+/*
+ *
+ * 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.
+ *
+ */
+
+#define _POSIX_C_SOURCE 1
+
+#include <proton/driver.h>
+
+/** @file
+ * Internal API for SSL/TLS support in the Driver Layer.
+ *
+ * Generic API to abstract the implementation of SSL/TLS from the Driver codebase.
+ *
+ */
+
+/** Get the SSL server object associated with a transport.
+ *
+ * A transport may be configured to be either an SSL server or an SSL client.  Those
+ * transports that will be used to accept incoming connections must be configured as an
+ * SSL server.
+ *
+ * @return a pointer to the SSL server object configured for this transport.  Returns NULL
+ * if the server cannot be configured, which would occur if no SSL support is available,
+ * or the transport has already been configured as an SSL client.
+ */
+pn_ssl_t *pn_ssl_server(pn_transport_t *transport);
+
+/** Get the SSL client object associated with a transport.
+ *
+ * A transport may be configured to be either an SSL server or an SSL client.  Those
+ * transports that will be used to initiate outbound connections must be configured as an
+ * SSL client.
+ *
+ * @return a pointer to the SSL client object configured for this transport.  Returns NULL
+ * if the client cannot be configured, which would occur if no SSL support is available,
+ * or the transport has already been configured as an SSL server.
+ */
+pn_ssl_t *pn_ssl_client(pn_transport_t *transport);
+
+/** Start the SSL/TLS shutdown handshake.
+ *
+ * The SSL/TLS shutdown involves a protocol handshake.  This call will initiate the
+ * shutdown process, which may not complete on return from this function.  Once the
+ * handshake is completed, the connector will be closed and pn_connector_closed() will
+ * return TRUE.
+ *
+ * @param[in,out] c the connector to shutdown.
+ */
+void pn_ssl_shutdown( pn_ssl_t *ssl);
+
+/** Release any SSL/TLS related resources used by the listener.
+ *
+ * @param[in,out] l the listener to clean up.
+ */
+void pn_ssl_free( pn_ssl_t *ssl);
+
+/** Check if the SSL/TLS layer has data ready for reading or writing
+ *
+ * @param[in] d the driver
+ * @return 0 if no data ready, else !0
+ */
+//int pn_driver_ssl_data_ready( pn_driver_t *d );
+
+// move data received from the network into the SSL layer
+ssize_t pn_ssl_input(pn_ssl_t *ssl, char *bytes, size_t available);
+
+// copy data generated by SSL into the network's output buffers
+ssize_t pn_ssl_output(pn_ssl_t *ssl, char *buffer, size_t max_size);
+
+
+void pn_ssl_trace(pn_ssl_t *ssl, pn_trace_t trace);
+
+#endif /* ssl-internal.h */

Propchange: qpid/proton/branches/openssl/proton-c/src/ssl/ssl-internal.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: qpid/proton/branches/openssl/proton-c/src/ssl/ssl_stub.c
URL: http://svn.apache.org/viewvc/qpid/proton/branches/openssl/proton-c/src/ssl/ssl_stub.c?rev=1387642&view=auto
==============================================================================
--- qpid/proton/branches/openssl/proton-c/src/ssl/ssl_stub.c (added)
+++ qpid/proton/branches/openssl/proton-c/src/ssl/ssl_stub.c Wed Sep 19 15:32:50 2012
@@ -0,0 +1,99 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#define _POSIX_C_SOURCE 1
+
+#include <proton/ssl.h>
+#include "ssl-internal.h"
+
+
+/** @file
+ * SSL/TLS support API.
+ *
+ * This file contains stub implementations of the SSL/TLS API.  This implementation is
+ * used if there is no SSL/TLS support in the system's environment.
+ */
+
+pn_ssl_t *pn_ssl_server(pn_transport_t *transport)
+{
+  return NULL;
+}
+
+pn_ssl_t *pn_ssl_client(pn_transport_t *transport)
+{
+  return NULL;
+}
+
+
+int pn_ssl_set_credentials(pn_ssl_t *ssl,
+                           const char *certificate_file,
+                           const char *private_key_file,
+                           const char *password)
+{
+  return -1;
+}
+
+int pn_ssl_set_trusted_ca_db(pn_ssl_t *ssl,
+                             const char *certificate_db)
+{
+  return -1;
+}
+
+int pn_ssl_allow_unsecured_client(pn_ssl_t *ssl)
+{
+  return -1;
+}
+
+
+int pn_ssl_set_peer_authentication(pn_ssl_t *ssl,
+                                   const pn_ssl_verify_mode_t mode,
+                                   const char *trusted_CAs)
+{
+  return -1;
+}
+
+
+int pn_ssl_get_peer_authentication(pn_ssl_t *ssl,
+                                   pn_ssl_verify_mode_t *mode,
+                                   char *trusted_CAs, size_t *trusted_CAs_size)
+{
+  return -1;
+}
+
+void pn_ssl_free( pn_ssl_t *ssl)
+{
+}
+
+void pn_ssl_trace(pn_ssl_t *ssl, pn_trace_t trace)
+{
+}
+
+ssize_t pn_ssl_input(pn_ssl_t *ssl, char *bytes, size_t available)
+{
+  return PN_EOS;
+}
+
+ssize_t pn_ssl_output(pn_ssl_t *ssl, char *buffer, size_t max_size)
+{
+  return PN_EOS;
+}
+
+

Propchange: qpid/proton/branches/openssl/proton-c/src/ssl/ssl_stub.c
------------------------------------------------------------------------------
    svn:eol-style = native



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