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/08/10 20:14:59 UTC

svn commit: r1371797 - in /qpid/proton/branches/driver_abstraction: examples/mailbox/ proton-c/ proton-c/include/proton/ proton-c/src/ proton-c/src/drivers/

Author: kgiusti
Date: Fri Aug 10 18:14:58 2012
New Revision: 1371797

URL: http://svn.apache.org/viewvc?rev=1371797&view=rev
Log:
checkpoint

Modified:
    qpid/proton/branches/driver_abstraction/examples/mailbox/post
    qpid/proton/branches/driver_abstraction/examples/mailbox/server
    qpid/proton/branches/driver_abstraction/proton-c/CMakeLists.txt
    qpid/proton/branches/driver_abstraction/proton-c/include/proton/driver.h
    qpid/proton/branches/driver_abstraction/proton-c/src/driver.c
    qpid/proton/branches/driver_abstraction/proton-c/src/driver_impl.h
    qpid/proton/branches/driver_abstraction/proton-c/src/drivers/driver_openssl.c

Modified: qpid/proton/branches/driver_abstraction/examples/mailbox/post
URL: http://svn.apache.org/viewvc/qpid/proton/branches/driver_abstraction/examples/mailbox/post?rev=1371797&r1=1371796&r2=1371797&view=diff
==============================================================================
--- qpid/proton/branches/driver_abstraction/examples/mailbox/post (original)
+++ qpid/proton/branches/driver_abstraction/examples/mailbox/post Fri Aug 10 18:14:58 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")
+
+        # if server wants 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,7 @@ class PostClient(object):
         self.port = port
         self.mailbox = mailbox
         self.logging = False
+        self.ca_database = ca_database
 
     def setup(self):
         """ Setup and configure the connection to the server.
@@ -68,6 +80,12 @@ 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)
+
+        # configure database of trusted CA's
+        if self.ca_database:
+            rc = pn_connector_ssl_client_init(self.cxtr, self.ca_database);
+            assert(rc == 0)
 
         # configure SASL
         self.sasl = pn_connector_sasl(self.cxtr)
@@ -148,7 +166,8 @@ def main():
 
     sender = PostClient(options.host,
                         options.port,
-                        options.mailbox)
+                        options.mailbox,
+                        options.ca_database)
     if options.verbose:
         sender.enableLogging()
 

Modified: qpid/proton/branches/driver_abstraction/examples/mailbox/server
URL: http://svn.apache.org/viewvc/qpid/proton/branches/driver_abstraction/examples/mailbox/server?rev=1371797&r1=1371796&r2=1371797&view=diff
==============================================================================
--- qpid/proton/branches/driver_abstraction/examples/mailbox/server (original)
+++ qpid/proton/branches/driver_abstraction/examples/mailbox/server Fri Aug 10 18:14:58 2012
@@ -38,10 +38,35 @@ class Options(object):
         parser.add_option("-v", "--verbose",
                           action="store_false", dest="verbose", default=True,
                           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")
+
+        # 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,12 +80,20 @@ 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.counter = 0
@@ -75,6 +108,16 @@ 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)
+            rc = pn_listener_ssl_server_init(self.listener, self.certificate_file,
+                                             self.certificate_key_file,
+                                             self.key_file_password,
+                                             self.ca_database);
+            assert(rc == 0)
+            if not self.require_encryption:
+                rc = pn_listener_ssl_allow_unsecured_clients(self.listener)
+                assert(rc == 0)
         return True
 
 
@@ -345,7 +388,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()
 

Modified: qpid/proton/branches/driver_abstraction/proton-c/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/proton/branches/driver_abstraction/proton-c/CMakeLists.txt?rev=1371797&r1=1371796&r2=1371797&view=diff
==============================================================================
--- qpid/proton/branches/driver_abstraction/proton-c/CMakeLists.txt (original)
+++ qpid/proton/branches/driver_abstraction/proton-c/CMakeLists.txt Fri Aug 10 18:14:58 2012
@@ -61,6 +61,7 @@ endif (POLLER STREQUAL poll)
 # Link in openssl if present
 if (SSL_IMPL STREQUAL openssl)
   set (pn_driver_ssl_impl src/drivers/driver_openssl.c)
+  set (LINK_DEPS ${LINK_DEPS} ssl crypto)
 else (SSL_IMPL STREQUAL openssl)
   set (pn_driver_ssl_impl src/drivers/driver_no_ssl.c)
 endif (SSL_IMPL STREQUAL openssl)

Modified: qpid/proton/branches/driver_abstraction/proton-c/include/proton/driver.h
URL: http://svn.apache.org/viewvc/qpid/proton/branches/driver_abstraction/proton-c/include/proton/driver.h?rev=1371797&r1=1371796&r2=1371797&view=diff
==============================================================================
--- qpid/proton/branches/driver_abstraction/proton-c/include/proton/driver.h (original)
+++ qpid/proton/branches/driver_abstraction/proton-c/include/proton/driver.h Fri Aug 10 18:14:58 2012
@@ -159,29 +159,34 @@ void pn_listener_close(pn_listener_t *li
  */
 void pn_listener_free(pn_listener_t *listener);
 
-/** Set the identifying certificate for the listener.  This certificate will set the
- * identity for all connectors created from this listener.  Setting these parameters
- * configures the pn_listener_t to use SSL/TLS on all connectors created from this
- * listener (see ::pn_listener_accept).  The certificate will be used for authenticating
- * this server to connecting clients and encrypting the data stream.
+/** Configure the listener as an SSL server by setting the identifying certificate for the
+ * server.
+ *
+ * This certificate will set the identity for all connectors created from this listener.
+ * Setting these parameters configures the pn_listener_t to use SSL/TLS on all connectors
+ * created from this listener (see ::pn_listener_accept).  The certificate will be used
+ * for authenticating this server to connecting clients and encrypting the data stream.
  *
  * @param[in] listener the listener that will provide this certificate.
- * @param[in] certificate_file path to file containing the certificate.
+ * @param[in] certificate_file path to file containing the identifying certificate.
  * @param[in] private_key_file path to file 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.
+ * @param[in] certificate_db (optional) database of trusted CAs.  Required if client authentication used, or the certificate chain is incomplete.
+ *
  * @return 0 on success
  */
-int pn_listener_ssl_set_certificate(pn_listener_t *listener,
-                                    const char *certificate_file,
-                                    const char *private_key_file,
-                                    const char *password);
+int pn_listener_ssl_server_init(pn_listener_t *listener,
+                                const char *certificate_file,
+                                const char *private_key_file,
+                                const char *password,
+                                const char *certificate_db);
 
 
 /** Permit a listener that has been configured to use SSL/TLS to accept connection
  * requests from clients that are not using SSL/TLS.  This configures the listener to
  * "sniff" the incoming client data stream, and dynamically determine whether SSL/TLS is
  * being used on a per-client basis.  This option is disabled by default: only clients
- * using SSL/TLS are accepted.  See ::pn_listener_ssl_set_certificate.
+ * using SSL/TLS are accepted.  See ::pn_listener_ssl_server_init.
  *
  * @param[in] listener the listener that will accept client connections.
  * @return 0 on success
@@ -304,49 +309,47 @@ bool pn_connector_closed(pn_connector_t 
 void pn_connector_free(pn_connector_t *connector);
 
 
-/** Configure the set of trusted server certificates for this connector.  This causes the
- * connector to use SSL/TLS to authenticate the peer.  It is intended to be used by a
- * client that is attempting to connecto to a trusted server.  See ::pn_driver_connector
- * ::pn_connector ::pn_connector_fd
+/** Configure the set of trusted certificates for this client.  This causes the connector
+ * to use SSL/TLS to authenticate the server and encrypt traffic.  It is intended to be
+ * used by a client that is attempting to connect to a trusted server.  See
+ * ::pn_driver_connector ::pn_connector ::pn_connector_fd
  *
- * @param[in] listener the listener that will use the certificates.
- * @param[in] certificates path to file containing certificates for trusted servers.
- * @return 0 on success
+ * @param[in] connector the connector that will use SSL/TLS
+ * @param[in] certificate_db database of trusted CAs, used to authenticate the server.
  *
- * @brief For connectors that have been created directly from the driver (client
- * connections), rather than from the listener.  See
- * ::pn_listener_ssl_set_trusted_certificates.
+ * @return 0 on success
  */
-int pn_connector_ssl_set_trusted_certificates(pn_connector_t *connector,
-                                              const char *certificates);
+int pn_connector_ssl_client_init(pn_connector_t *connector,
+                                 const char *certificate_db);
 
-
-
-/** Configure the identifying certificate for the connector.  Used for client connections
- * that will have to authenticate with the remote server.
+/** Configure the identifying certificate for the connector.  Used for those client
+ * connections that will have to authenticate -to- the remote server.
  *
- * @param[in] connector the connector that will provide this certificate.
+ * @param[in] connector the connector that will advertise the certificate.
  * @param[in] certificate_file path to file containing the certificate.
  * @param[in] private_key_file path to file 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_connector_ssl_set_certificate(pn_connector_t *connector,
-                                     const char *certificate,
-                                     const char *private_key,
-                                     const char *private_key_password);
+int pn_connector_ssl_set_client_auth(pn_connector_t *connector,
+                                     const char *certificate_file,
+                                     const char *private_key_file,
+                                     const char *password);
 
 
-/** Force the peer to authenticate.  This is intended to be used on those connectors that
- * have been created by a listener - it permits the server to force authentication of the
- * connected client.  See ::pn_listener_ssl_set_certificate.
+
+/** Force the peer (client) to authenticate.  This is intended to be used on those
+ * connectors that have been created by a listener - it permits the server to force
+ * authentication of the connected client.  See ::pn_listener_ssl_set_client_auth
  *
  * @param[in] connector the connector that will require authentication from its peer.
- * @param[in] certificates if set, a restricted set of allowable certificates (subset of
- *     trusted certificates configured).
+ * @param[in] trusted_CAs_file a file containing certificates of those CA that will be
+ *  advertised to the client as trusted CAs.
+ *
  * @return 0 on success
  */
-int pn_connector_ssl_authenticate_peer(pn_connector_t *connector,
-                                       const char *certificates);
+int pn_connector_ssl_authenticate_client(pn_connector_t *connector,
+                                         const char *trusted_CAs_file);
 
 #endif /* driver.h */

Modified: qpid/proton/branches/driver_abstraction/proton-c/src/driver.c
URL: http://svn.apache.org/viewvc/qpid/proton/branches/driver_abstraction/proton-c/src/driver.c?rev=1371797&r1=1371796&r2=1371797&view=diff
==============================================================================
--- qpid/proton/branches/driver_abstraction/proton-c/src/driver.c (original)
+++ qpid/proton/branches/driver_abstraction/proton-c/src/driver.c Fri Aug 10 18:14:58 2012
@@ -116,6 +116,7 @@ pn_listener_t *pn_listener_fd(pn_driver_
   l->pending = false;
   l->fd = fd;
   l->context = context;
+  l->ssl = NULL;
 
   pn_listener_impl_init(l);
 
@@ -293,6 +294,7 @@ pn_connector_t *pn_connector_fd(pn_drive
   c->output_done = false;
   c->context = context;
   c->listener = NULL;
+  c->ssl = NULL;
 
   pn_connector_impl_init(c);
 

Modified: qpid/proton/branches/driver_abstraction/proton-c/src/driver_impl.h
URL: http://svn.apache.org/viewvc/qpid/proton/branches/driver_abstraction/proton-c/src/driver_impl.h?rev=1371797&r1=1371796&r2=1371797&view=diff
==============================================================================
--- qpid/proton/branches/driver_abstraction/proton-c/src/driver_impl.h (original)
+++ qpid/proton/branches/driver_abstraction/proton-c/src/driver_impl.h Fri Aug 10 18:14:58 2012
@@ -66,6 +66,8 @@ void pn_listener_impl_destroy( struct pn
 #define PN_SEL_RD (0x0001)
 #define PN_SEL_WR (0x0002)
 
+struct pn_listener_ssl_impl_t;
+
 struct pn_connector_t {
   pn_driver_t *driver;
   pn_connector_t *connector_next;
@@ -98,6 +100,7 @@ struct pn_connector_t {
   void *context;
 
   struct pn_connector_impl_t *impl;
+  struct pn_connector_ssl_impl_t *ssl;
 };
 
 int pn_connector_impl_init( struct pn_connector_t *);

Modified: qpid/proton/branches/driver_abstraction/proton-c/src/drivers/driver_openssl.c
URL: http://svn.apache.org/viewvc/qpid/proton/branches/driver_abstraction/proton-c/src/drivers/driver_openssl.c?rev=1371797&r1=1371796&r2=1371797&view=diff
==============================================================================
--- qpid/proton/branches/driver_abstraction/proton-c/src/drivers/driver_openssl.c (original)
+++ qpid/proton/branches/driver_abstraction/proton-c/src/drivers/driver_openssl.c Fri Aug 10 18:14:58 2012
@@ -22,6 +22,12 @@
 #define _POSIX_C_SOURCE 1
 
 #include <proton/driver.h>
+#include "../driver_impl.h"
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 
 /** @file
@@ -32,36 +38,230 @@
  */
 
 
+struct pn_listener_ssl_impl_t {
+    SSL_CTX *ctx;
+    bool allow_unsecured;
+    bool ca_db;
+    char *keyfile_pw;
+};
+typedef struct pn_listener_ssl_impl_t pn_listener_ssl_impl_t;
+
+
+struct pn_connector_ssl_impl_t {
+
+    enum { SSL_CLIENT, SSL_SERVER } mode;
+    SSL_CTX *ctx;
+    SSL *ssl;
+    BIO *sbio;
+    char *keyfile_pw;
+
+    int state;  /// ????
+    int need_read;
+    int need_write;
+    int read_blocked_on_write;
+    int write_blocked_on_read;
+    int read_stalled;
+
+};
+typedef struct pn_connector_ssl_impl_t pn_connector_ssl_impl_t;
 
-int pn_listener_ssl_set_certificate(pn_listener_t *listener,
-                                    const char *certificate_file,
-                                    const char *private_key_file,
-                                    const char *password)
+
+static char *copy_str(const char *str)
 {
-    return -1;
+    int len = strlen(str);
+    char *s = (char *)malloc(len + 1);
+    if (s) strcpy(s, str);
+    return s;
+}
+
+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));
+}
+
+
+// Configure the database containing trusted CA certificates
+static int configure_database(SSL_CTX *ctx, const char *certificate_db)
+{
+    // 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) {
+        fprintf(stderr, "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( ctx, file, dir ) != 1) {
+        fprintf(stderr, "SSL_CTX_load_verify_locations( %s ) failed\n", certificate_db);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+int pn_listener_ssl_server_init(pn_listener_t *listener,
+                                const char *certificate_file,
+                                const char *private_key_file,
+                                const char *password,
+                                const char *certificate_db)
+{
+    listener->ssl = calloc(1, sizeof(pn_listener_ssl_impl_t));
+    if (!listener->ssl) {
+        perror("calloc()");
+        return -1;
+    }
+    pn_listener_ssl_impl_t *impl = listener->ssl;
+
+    SSL_library_init();
+    impl->ctx = SSL_CTX_new(SSLv23_server_method());
+    if (!impl->ctx) {
+        perror("unable to initialize SSL context");
+        return -2;
+    }
+
+    if (SSL_CTX_use_certificate_chain_file(impl->ctx, certificate_file) != 1) {
+        fprintf(stderr, "SSL_CTX_use_certificate_chain_file( %s ) failed\n", certificate_file);
+        return -3;
+    }
+
+    if (password) {
+        impl->keyfile_pw = copy_str(password);  // @todo: obfuscate me!!!
+        SSL_CTX_set_default_passwd_cb(impl->ctx, keyfile_pw_cb);
+        SSL_CTX_set_default_passwd_cb_userdata(impl->ctx, impl->keyfile_pw);
+    }
+
+    if (SSL_CTX_use_PrivateKey_file(impl->ctx, private_key_file, SSL_FILETYPE_PEM) != 1) {
+        fprintf(stderr, "SSL_CTX_use_PrivateKey_file( %s ) failed\n", private_key_file);
+        return -4;
+    }
+
+    int rc = 0;
+    if (certificate_db) {
+        impl->ca_db = true;
+        rc = configure_database(impl->ctx, certificate_db);
+    }
+    return rc;
 }
 
 int pn_listener_ssl_allow_unsecured_clients(pn_listener_t *listener)
 {
-    return -1;
+    if (!listener->ssl) {
+        fprintf(stderr, "SSL not initialized");
+        return -1;
+    }
+
+    listener->ssl->allow_unsecured = true;
+    return 0;
 }
 
-int pn_connector_ssl_set_trusted_certificates(pn_connector_t *connector,
-                                              const char *certificates)
+
+
+int pn_connector_ssl_client_init(pn_connector_t *connector,
+                                 const char *certificate_db)
 {
-    return -1;
+    connector->ssl = calloc(1, sizeof(pn_connector_ssl_impl_t));
+    if (!connector->ssl) {
+        perror("calloc()");
+        return -1;
+    }
+    pn_connector_ssl_impl_t *impl = connector->ssl;
+
+    impl->mode = SSL_CLIENT;
+    SSL_library_init();
+    impl->ctx = SSL_CTX_new(SSLv23_client_method());
+    if (!impl->ctx) {
+        perror("unable to initialize SSL context");
+        return -2;
+    }
+
+    if (configure_database(impl->ctx, certificate_db)) {
+        return -3;
+    }
+
+    /* Force servers to authenticate */
+    SSL_CTX_set_verify( connector->ssl->ctx,
+                        SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+                        0 /*?verify callback?*/ );
+
+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+    SSL_CTX_set_verify_depth(connector->ssl->ctx, 1);
+#endif
+
+    return 0;
 }
 
-int pn_connector_ssl_set_certificate(pn_connector_t *connector,
-                                     const char *certificate,
-                                     const char *private_key,
-                                     const char *private_key_password)
+
+int pn_connector_ssl_set_client_auth(pn_connector_t *connector,
+                                     const char *certificate_file,
+                                     const char *private_key_file,
+                                     const char *password)
 {
-    return -1;
+    // @todo check state to verify not yet connected!
+
+    pn_connector_ssl_impl_t *impl = connector->ssl;
+
+    if (!impl || impl->mode != SSL_CLIENT) {
+        fprintf(stderr, "Error: connector not configured as SSL client.\n");
+        return -1;
+    }
+
+    if (SSL_CTX_use_certificate_chain_file(impl->ctx, certificate_file) != 1) {
+        fprintf(stderr, "SSL_CTX_use_certificate_chain_file( %s ) failed\n", certificate_file);
+        return -3;
+    }
+
+    if (password) {
+        impl->keyfile_pw = copy_str(password);  // @todo: obfuscate me!!!
+        SSL_CTX_set_default_passwd_cb(impl->ctx, keyfile_pw_cb);
+        SSL_CTX_set_default_passwd_cb_userdata(impl->ctx, impl->keyfile_pw);
+    }
+
+    if (SSL_CTX_use_PrivateKey_file(impl->ctx, private_key_file, SSL_FILETYPE_PEM) != 1) {
+        fprintf(stderr, "SSL_CTX_use_PrivateKey_file( %s ) failed\n", private_key_file);
+        return -4;
+    }
+
+    return 0;
 }
 
-int pn_connector_ssl_authenticate_peer(pn_connector_t *connector,
-                                       const char *certificates)
+
+int pn_connector_ssl_authenticate_client(pn_connector_t *connector,
+                                         const char *trusted_CAs_file)
 {
-    return -1;
+    pn_connector_ssl_impl_t *impl = connector->ssl;
+
+    if (!impl || impl->mode != SSL_SERVER) {
+        fprintf(stderr, "Error: connector not configured as SSL server.\n");
+    }
+
+    // @todo: make sure certificate_db is set...
+
+
+    // load the CA's that we trust - this will be sent to the client when client
+    // authentication is requested
+    STACK_OF(X509_NAME) *cert_names;
+    cert_names = SSL_load_client_CA_file( trusted_CAs_file );
+    if (cert_names != NULL)
+        SSL_set_client_CA_list(impl->ssl, cert_names);
+    else {
+        fprintf(stderr, "Unable to process file of trusted_CAs: %s\n", trusted_CAs_file);
+        return -1;
+    }
+
+    SSL_set_verify( impl->ssl,
+                    SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+                    0 /*?verify callback?*/);
+    return 0;
 }



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