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