Repository: qpid-proton
Updated Branches:
  refs/heads/master a49e36db8 -> e0feb3f2f


PROTON-1620: set locking function for old versions of openssl


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/434a2e77
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/434a2e77
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/434a2e77

Branch: refs/heads/master
Commit: 434a2e7731b757ac6a303725122d811aa90ff023
Parents: a49e36d
Author: Alan Conway <acon...@redhat.com>
Authored: Mon Oct 16 16:53:48 2017 +0100
Committer: Alan Conway <acon...@redhat.com>
Committed: Tue Oct 17 11:04:55 2017 +0100

----------------------------------------------------------------------
 examples/c/CMakeLists.txt                    |   2 +-
 examples/c/broker.c                          |  28 +-
 examples/c/example_test.py                   |   6 +
 examples/c/send-ssl.c                        | 229 ++++++++++++
 examples/c/ssl_certs/README.txt              |  24 ++
 examples/c/ssl_certs/tclient-certificate.p12 | Bin 0 -> 1032 bytes
 examples/c/ssl_certs/tclient-certificate.pem |  19 +
 examples/c/ssl_certs/tclient-full.p12        | Bin 0 -> 2476 bytes
 examples/c/ssl_certs/tclient-private-key.pem |  30 ++
 examples/c/ssl_certs/tserver-certificate.p12 | Bin 0 -> 1032 bytes
 examples/c/ssl_certs/tserver-certificate.pem |  19 +
 examples/c/ssl_certs/tserver-full.p12        | Bin 0 -> 2476 bytes
 examples/c/ssl_certs/tserver-private-key.pem |  30 ++
 proton-c/src/ssl/openssl.c                   | 406 +++++++++++++---------
 proton-c/src/tests/proactor.c                |   1 -
 15 files changed, 627 insertions(+), 167 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt
index 4bfff2d..48ae9b2 100644
--- a/examples/c/CMakeLists.txt
+++ b/examples/c/CMakeLists.txt
@@ -34,7 +34,7 @@ else()
   set(test_path "${CMAKE_CURRENT_BINARY_DIR}:$ENV{PATH}")
 endif()
 
-foreach (name broker send receive direct send-abort)
+foreach (name broker send receive direct send-abort send-ssl)
   add_executable(c-${name} ${name}.c)
   target_link_libraries(c-${name} ${Proton_Proactor_LIBRARIES} 
${Proton_Core_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
   set_target_properties(c-${name} PROPERTIES

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/broker.c
----------------------------------------------------------------------
diff --git a/examples/c/broker.c b/examples/c/broker.c
index d6cb753..541fbff 100644
--- a/examples/c/broker.c
+++ b/examples/c/broker.c
@@ -23,12 +23,27 @@
 #include <proton/listener.h>
 #include <proton/proactor.h>
 #include <proton/sasl.h>
+#include <proton/ssl.h>
 #include <proton/transport.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+/* The ssl_certs subdir must be in the current directory for an ssl-enabled 
broker */
+#define SSL_FILE(NAME) "ssl_certs/" NAME
+#define SSL_PW "tserverpw"
+/* Windows vs. OpenSSL certificates */
+#if defined(_WIN32)
+#  define CERTIFICATE(NAME) SSL_FILE(NAME "-certificate.p12")
+#  define SET_CREDENTIALS(DOMAIN, NAME)                                 \
+  pn_ssl_domain_set_credentials(DOMAIN, SSL_FILE(NAME "-full.p12"), "", SSL_PW)
+#else
+#  define CERTIFICATE(NAME) SSL_FILE(NAME "-certificate.pem")
+#  define SET_CREDENTIALS(DOMAIN, NAME)                                 \
+  pn_ssl_domain_set_credentials(DOMAIN, CERTIFICATE(NAME), SSL_FILE(NAME 
"-private-key.pem"), SSL_PW)
+#endif
+
 /* Simple re-sizable vector that acts as a queue */
 #define VEC(T) struct { T* data; size_t len, cap; }
 
@@ -199,6 +214,7 @@ typedef struct broker_t {
   const char *container_id;     /* AMQP container-id */
   queues_t queues;
   bool finished;
+  pn_ssl_domain_t *ssl_domain;
 } broker_t;
 
 void broker_stop(broker_t *b) {
@@ -283,10 +299,15 @@ static void handle(broker_t* b, pn_event_t* e) {
      break;
 
    case PN_CONNECTION_BOUND: {
-     /* Turn off security */
+     /* Allow anonymous connections by SASL */
      pn_transport_t *t = pn_connection_transport(c);
      pn_transport_require_auth(t, false);
      pn_sasl_allowed_mechs(pn_sasl(t), "ANONYMOUS");
+     /* Accept SSL connections if possible, but also plain connections.
+        See the call to pn_ssl_domain_allow_unsecured_client() in main() */
+     if (b->ssl_domain) {
+       pn_ssl_init(pn_ssl(pn_event_transport(e)), b->ssl_domain, NULL);
+     }
      break;
    }
    case PN_CONNECTION_REMOTE_OPEN: {
@@ -427,7 +448,9 @@ int main(int argc, char **argv) {
   queues_init(&b.queues);
   b.container_id = argv[0];
   b.threads = 4;
-
+  b.ssl_domain = pn_ssl_domain(PN_SSL_MODE_SERVER);
+  SET_CREDENTIALS(b.ssl_domain, "tserver");
+  pn_ssl_domain_allow_unsecured_client(b.ssl_domain); /* Allow SSL and plain 
connections */
   {
   /* Listen on addr */
   char addr[PN_MAX_ADDR];
@@ -449,6 +472,7 @@ int main(int argc, char **argv) {
   }
   pn_proactor_free(b.proactor);
   free(threads);
+  pn_ssl_domain_free(b.ssl_domain);
   return 0;
   }
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/example_test.py
----------------------------------------------------------------------
diff --git a/examples/c/example_test.py b/examples/c/example_test.py
index 9cd0b13..31d941f 100644
--- a/examples/c/example_test.py
+++ b/examples/c/example_test.py
@@ -116,5 +116,11 @@ class CExampleTest(ProcTestCase):
             self.maxDiff = None
             self.assertMultiLineEqual(expect, d.wait_exit())
 
+    def test_send_ssl_receive(self):
+        """Send first then receive"""
+        with Broker(self) as b:
+            self.assertEqual(send_expect(), self.runex("send-ssl", b.port))
+            self.assertMultiLineEqual(receive_expect(), self.runex("receive", 
b.port))
+
 if __name__ == "__main__":
     unittest.main()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/send-ssl.c
----------------------------------------------------------------------
diff --git a/examples/c/send-ssl.c b/examples/c/send-ssl.c
new file mode 100644
index 0000000..8e0722e
--- /dev/null
+++ b/examples/c/send-ssl.c
@@ -0,0 +1,229 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/connection.h>
+#include <proton/condition.h>
+#include <proton/delivery.h>
+#include <proton/link.h>
+#include <proton/message.h>
+#include <proton/proactor.h>
+#include <proton/session.h>
+#include <proton/ssl.h>
+#include <proton/transport.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct app_data_t {
+  const char *host, *port;
+  const char *amqp_address;
+  const char *container_id;
+  int message_count;
+
+  pn_proactor_t *proactor;
+  pn_rwbytes_t message_buffer;
+  int sent;
+  int acknowledged;
+  pn_ssl_domain_t *ssl_domain;
+} app_data_t;
+
+static int exit_code = 0;
+
+/* Note must be run in the current directory to find certificate files */
+#define SSL_FILE(NAME) CMAKE_CURRENT_SOURCE_DIR "/ssl_certs/" NAME
+#define SSL_PW "tclientpw"
+/* Windows vs. OpenSSL certificates */
+#if defined(_WIN32)
+#  define CERTIFICATE(NAME) SSL_FILE(NAME "-certificate.p12")
+#  define SET_CREDENTIALS(DOMAIN, NAME)                                 \
+  pn_ssl_domain_set_credentials(DOMAIN, SSL_FILE(NAME "-full.p12"), "", SSL_PW)
+#else
+#  define CERTIFICATE(NAME) SSL_FILE(NAME "-certificate.pem")
+#  define SET_CREDENTIALS(DOMAIN, NAME)                                 \
+  pn_ssl_domain_set_credentials(DOMAIN, CERTIFICATE(NAME), SSL_FILE(NAME 
"-private-key.pem"), SSL_PW)
+#endif
+
+
+static void check_condition(pn_event_t *e, pn_condition_t *cond) {
+  if (pn_condition_is_set(cond)) {
+    fprintf(stderr, "%s: %s: %s\n", pn_event_type_name(pn_event_type(e)),
+            pn_condition_get_name(cond), pn_condition_get_description(cond));
+    pn_connection_close(pn_event_connection(e));
+    exit_code = 1;
+  }
+}
+
+/* Create a message with a map { "sequence" : number } encode it and return 
the encoded buffer. */
+static pn_bytes_t encode_message(app_data_t* app) {
+  /* Construct a message with the map { "sequence": app.sent } */
+  pn_message_t* message = pn_message();
+  pn_data_t* body = pn_message_body(message);
+  pn_data_put_int(pn_message_id(message), app->sent); /* Set the message_id 
also */
+  pn_data_put_map(body);
+  pn_data_enter(body);
+  pn_data_put_string(body, pn_bytes(sizeof("sequence")-1, "sequence"));
+  pn_data_put_int(body, app->sent); /* The sequence number */
+  pn_data_exit(body);
+
+  /* encode the message, expanding the encode buffer as needed */
+  if (app->message_buffer.start == NULL) {
+    static const size_t initial_size = 128;
+    app->message_buffer = pn_rwbytes(initial_size, 
(char*)malloc(initial_size));
+  }
+  /* app->message_buffer is the total buffer space available. */
+  /* mbuf wil point at just the portion used by the encoded message */
+  {
+  pn_rwbytes_t mbuf = pn_rwbytes(app->message_buffer.size, 
app->message_buffer.start);
+  int status = 0;
+  while ((status = pn_message_encode(message, mbuf.start, &mbuf.size)) == 
PN_OVERFLOW) {
+    app->message_buffer.size *= 2;
+    app->message_buffer.start = (char*)realloc(app->message_buffer.start, 
app->message_buffer.size);
+    mbuf.size = app->message_buffer.size;
+    mbuf.start = app->message_buffer.start;
+  }
+  if (status != 0) {
+    fprintf(stderr, "error encoding message: %s\n", 
pn_error_text(pn_message_error(message)));
+    exit(1);
+  }
+  pn_message_free(message);
+  return pn_bytes(mbuf.size, mbuf.start);
+  }
+}
+
+/* Returns true to continue, false if finished */
+static bool handle(app_data_t* app, pn_event_t* event) {
+  switch (pn_event_type(event)) {
+
+   case PN_CONNECTION_INIT: {
+     pn_connection_t* c = pn_event_connection(event);
+     pn_session_t* s = pn_session(pn_event_connection(event));
+     pn_connection_set_container(c, app->container_id);
+     pn_connection_open(c);
+     pn_session_open(s);
+     {
+     pn_link_t* l = pn_sender(s, "my_sender");
+     pn_terminus_set_address(pn_link_target(l), app->amqp_address);
+     pn_link_open(l);
+     break;
+     }
+   }
+
+   case PN_CONNECTION_BOUND: {
+     int err =  pn_ssl_init(pn_ssl(pn_event_transport(event)), 
app->ssl_domain, NULL);
+     if (err) fprintf(stderr, "error encoding message: %s\n", pn_code(err));
+   }
+
+   case PN_LINK_FLOW: {
+     /* The peer has given us some credit, now we can send messages */
+     pn_link_t *sender = pn_event_link(event);
+     while (pn_link_credit(sender) > 0 && app->sent < app->message_count) {
+       ++app->sent;
+       /* Use sent counter as unique delivery tag. */
+       pn_delivery(sender, pn_dtag((const char *)&app->sent, 
sizeof(app->sent)));
+       {
+       pn_bytes_t msgbuf = encode_message(app);
+       pn_link_send(sender, msgbuf.start, msgbuf.size);
+       }
+       pn_link_advance(sender);
+     }
+     break;
+   }
+
+   case PN_DELIVERY: {
+     /* We received acknowledgedment from the peer that a message was 
delivered. */
+     pn_delivery_t* d = pn_event_delivery(event);
+     if (pn_delivery_remote_state(d) == PN_ACCEPTED) {
+       if (++app->acknowledged == app->message_count) {
+         printf("%d messages sent and acknowledged\n", app->acknowledged);
+         pn_connection_close(pn_event_connection(event));
+         /* Continue handling events till we receive TRANSPORT_CLOSED */
+       }
+     } else {
+       fprintf(stderr, "unexpected delivery state %d\n", 
(int)pn_delivery_remote_state(d));
+       pn_connection_close(pn_event_connection(event));
+       exit_code=1;
+     }
+     break;
+   }
+
+   case PN_TRANSPORT_CLOSED:
+    check_condition(event, pn_transport_condition(pn_event_transport(event)));
+    break;
+
+   case PN_CONNECTION_REMOTE_CLOSE:
+    check_condition(event, 
pn_connection_remote_condition(pn_event_connection(event)));
+    pn_connection_close(pn_event_connection(event));
+    break;
+
+   case PN_SESSION_REMOTE_CLOSE:
+    check_condition(event, 
pn_session_remote_condition(pn_event_session(event)));
+    pn_connection_close(pn_event_connection(event));
+    break;
+
+   case PN_LINK_REMOTE_CLOSE:
+   case PN_LINK_REMOTE_DETACH:
+    check_condition(event, pn_link_remote_condition(pn_event_link(event)));
+    pn_connection_close(pn_event_connection(event));
+    break;
+
+   case PN_PROACTOR_INACTIVE:
+    return false;
+
+   default: break;
+  }
+  return true;
+}
+
+void run(app_data_t *app) {
+  /* Loop and handle events */
+  do {
+    pn_event_batch_t *events = pn_proactor_wait(app->proactor);
+    pn_event_t *e;
+    for (e = pn_event_batch_next(events); e; e = pn_event_batch_next(events)) {
+      if (!handle(app, e)) {
+        return;
+      }
+    }
+    pn_proactor_done(app->proactor, events);
+  } while(true);
+}
+
+int main(int argc, char **argv) {
+  struct app_data_t app = {0};
+  char addr[PN_MAX_ADDR];
+
+  app.container_id = argv[0];   /* Should be unique */
+  app.host = (argc > 1) ? argv[1] : "";
+  app.port = (argc > 2) ? argv[2] : "amqp";
+  app.amqp_address = (argc > 3) ? argv[3] : "examples";
+  app.message_count = (argc > 4) ? atoi(argv[4]) : 10;
+  app.ssl_domain = pn_ssl_domain(PN_SSL_MODE_CLIENT);
+
+  app.proactor = pn_proactor();
+  pn_proactor_addr(addr, sizeof(addr), app.host, app.port);
+  pn_proactor_connect(app.proactor, pn_connection(), addr);
+  run(&app);
+
+  pn_ssl_domain_free(app.ssl_domain);
+  pn_proactor_free(app.proactor);
+  free(app.message_buffer.start);
+  return exit_code;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/ssl_certs/README.txt
----------------------------------------------------------------------
diff --git a/examples/c/ssl_certs/README.txt b/examples/c/ssl_certs/README.txt
new file mode 100644
index 0000000..9a8a4f9
--- /dev/null
+++ b/examples/c/ssl_certs/README.txt
@@ -0,0 +1,24 @@
+This directory contains basic self signed test certificates for use by
+proton examples.
+
+The ".pem" files are in the format expected by proton implementations
+using OpenSSL.  The ".p12" file are for Windows implementations using
+SChannel.
+
+The commands used to generate the certificates follow.
+
+
+make_pn_cert()
+{
+  name=$1
+  subject=$2
+  passwd=$3
+  # create the pem files
+  openssl req -newkey rsa:2048 -keyout $name-private-key.pem -out 
$name-certificate.pem -subj $subject -passout pass:$passwd -x509 -days 3650
+  # create the p12 files
+  openssl pkcs12 -export -out $name-full.p12 -passin pass:$passwd -passout 
pass:$passwd -inkey $name-private-key.pem -in $name-certificate.pem -name $name
+  openssl pkcs12 -export -out $name-certificate.p12 -in $name-certificate.pem 
-name $name -nokeys -passout pass:
+}
+
+make_pn_cert tserver /CN=test_server/OU=proton_test tserverpw
+make_pn_cert tclient /CN=test_client/OU=proton_test tclientpw

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/ssl_certs/tclient-certificate.p12
----------------------------------------------------------------------
diff --git a/examples/c/ssl_certs/tclient-certificate.p12 
b/examples/c/ssl_certs/tclient-certificate.p12
new file mode 100644
index 0000000..4d0e000
Binary files /dev/null and b/examples/c/ssl_certs/tclient-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/ssl_certs/tclient-certificate.pem
----------------------------------------------------------------------
diff --git a/examples/c/ssl_certs/tclient-certificate.pem 
b/examples/c/ssl_certs/tclient-certificate.pem
new file mode 100644
index 0000000..8088e2e
--- /dev/null
+++ b/examples/c/ssl_certs/tclient-certificate.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDKzCCAhOgAwIBAgIJAIV7frIjftgcMA0GCSqGSIb3DQEBCwUAMCwxFDASBgNV
+BAMMC3Rlc3RfY2xpZW50MRQwEgYDVQQLDAtwcm90b25fdGVzdDAeFw0xNTExMjcx
+ODEwMzlaFw0yNTExMjQxODEwMzlaMCwxFDASBgNVBAMMC3Rlc3RfY2xpZW50MRQw
+EgYDVQQLDAtwcm90b25fdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAPCIS4qUdOtQplUxZ6WW0LXcvosqFP6qOiCARLSEWpR3B8bq213rzefwwfcM
+4TtMr88bP+huLKmlyMfwpl8yB88eXkscPgaAce2zk24urWkFXKSQ6GPitWBLGqBa
+V+W0wJ4mfW7MwefVslWfGXI381QEUlBHjkFG30AtzMMTRj2GK2JqUlRXZPljGyB7
+WcXwxcoS+HkKV7FtHWSkLAzyXwQ9vsCUEYdWTUaGXfCUNRSRV7h1LIANbu03NxV0
+XdEl7WXcr7tuTw3axeUGhRFVhLegrxKLuZTTno4aAJnEr8uaDzjxvXnv3Ne2igvy
+gRfZgOMx+XrZEob9OpAoRghQt4cCAwEAAaNQME4wHQYDVR0OBBYEFE4vbyiM0RjG
+TLMLLGGhMZE/5x1GMB8GA1UdIwQYMBaAFE4vbyiM0RjGTLMLLGGhMZE/5x1GMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAErr/rvLS9Ig0UCMwh1J1lA9
+/gvXf93iIK/SjrFIAqYRmfZxg4husfoes8t2hFUeuqoH05TuSOoXG8p8DpgTSGmF
+jAFe+T90vJZTm0oqZkkkI/hdzjGQoHURRp9/O2Z/lm39KSKGVAN5pUWCUDi/G5iS
+P9LZPJN6a5syXMrR6x62IPxAXowlpXkRghKClF3zPOaOBTzT1V27EkI8IEgC+p45
+246EooLnw8ibB+ucNc3KHNzpgKGVd/622+I+Q5eg9AT9PLFttP+R2ECsrVDDPYuA
+p0qaSnwgeozj/d6K3FOgKKEKbzBmpWgkv0jdcVk18aPMHypI/RDtZ/+3ET2Ksi8=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/ssl_certs/tclient-full.p12
----------------------------------------------------------------------
diff --git a/examples/c/ssl_certs/tclient-full.p12 
b/examples/c/ssl_certs/tclient-full.p12
new file mode 100644
index 0000000..ad2d7d3
Binary files /dev/null and b/examples/c/ssl_certs/tclient-full.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/ssl_certs/tclient-private-key.pem
----------------------------------------------------------------------
diff --git a/examples/c/ssl_certs/tclient-private-key.pem 
b/examples/c/ssl_certs/tclient-private-key.pem
new file mode 100644
index 0000000..e5c114d
--- /dev/null
+++ b/examples/c/ssl_certs/tclient-private-key.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQICy6ghWp45z4CAggA
+MBQGCCqGSIb3DQMHBAiVdDoo4NIghQSCBMixGm1bm/omMxsaKnIPO7zm5dyLexJ+
+yTFpmh2KV7kQqmpzCyIOdoG6K8YqFnie2XdFWm3S8faRHoMq54bDmyEWIxfQPq5f
+I1iYFbIZkbnhUvK53RActsEUMf0locS4xylU7VQK3XTAwp0TVip3Lp3ehEMEdcXL
+iUWibGsoTPKcY9MIWGXZAJXsEXoeHt6k2hHo1G4E0/Bi6mLW1LY/cxZCjHTGD6qI
+Kt54SCCDvinqVa+rixw6yX9F14EA6bhALami8e+Ccd3lqHOyYlXcBaSS1ezCg6ig
+oNK97mC+gEGy1KlkZDKWXclFoOCBXRBe4DByre6Rlq3yeI9L42bvAuSBSmf5QT5g
+73Yl8vjEAKR65awBT09dPuKu7t+Fb6vkwF8/t+uyj9IuL+42UuXhMLK3ohf+6DbU
+8/zB4y3GXI80QmWM0+Wx4n6khFhPFLHt2q0Sn6V9PG1vtHyiq50oSCoyrPQLaecp
+hefnMCFBYTcT3JUwmoVGGy0boIAwL7T4aGsMt7QhwOx5tU35tKFxyY7m4fX14AKo
+2EIy+TPQwCGkGf3Puy/Pc9VA8IAxB5+WwSrjk+NeCv88eIX7gy43k4rCr+OmD9FF
+wknr3xoP3KYhNXjdZ4Ep/1UHSK+JAtzzbNLQjDcqN+gQPg/yUX6ih0j5K3Wvh9bK
+E/DvzbpJroUZPgzR+8z5O68CfsD+OIdpHBFTKqAFmzvUuqpADpr998LdCjD+lW+V
+xZZgZa8KEblwgiH3fdGbYl46Ho1zrZisf439DbqyybAuBIQB4NSZcL/MAgVGO17k
+QDpVElWZWYrFm4CFTcvS2HvIzRmbefF5m5oJedsN7Q6WQCp+3gnwYx1xIOknd7pW
+N4AHNnqjscSj9yACj/EiBVKAKNnC5H7ZGZTsaAjMETZyjLXfI2AZ3Fviz4zFR+oz
+NkAfFB6WUpRpl7H02FzrzYT7XkkLcXd6H6g+mv2iDa9uKWk/PS2QlqnJt8/dHEHD
+JKTG331yDK5GHlKAVGF3nP5BwFGgTQMuSoeiOervMXPUwDpQ8OaYkuaRej0cZLgT
+kAF9sUjqdsoYNcXDFHALp6y5g8qYkfrxrlIbKs82zIsmB5I+dtZbUaD3a0zAUrmW
+5Xm3Pc9dVP0EXKwfHz6zqPReEw2yYLisB5IoHd4M2wa3GzHBdra1ij4QTmvd3o7e
+buGFoX8KJQAcig0zpbYkoDP2gPhIh9rY4unVPQNX1Q8/wRsiJAZZsYvZY+A+SmuZ
+bwSwk+8ZJRsFzdYYYhQeRytD5cDAIQiClcI5Yj4T9dWQV/gf0N/wIBDNTMp0jJAy
+1l7PuXTfGZodNJWZH0oqsrNoWbn/k67NildvvofIKX+h09Nxszr670Pvj0qoHd5/
+CWq30lnxoJBUgbikFOz6ZuuHi/ZiCXL+haH+v8hJKN5ptRKnyYJQHchRB/IOGRoT
+5lmWxo8a7K+yXhp0VBDHJfw3685ms0xQX8Xj4X3MEuN64zd0fB1JmhtP12ydK85J
+ABawNKlRQPw5weckwtCviXQX+vX25S/xu3xA6IuqlHyqL/1t3DICzuxeOyT2mZxD
+tKQxEgNihPvu32vn9m74qA3adEaxuWPRkPZuTeITHOkMTZolvqYX/5olBsSgYwka
+7/g=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/ssl_certs/tserver-certificate.p12
----------------------------------------------------------------------
diff --git a/examples/c/ssl_certs/tserver-certificate.p12 
b/examples/c/ssl_certs/tserver-certificate.p12
new file mode 100644
index 0000000..f38b67d
Binary files /dev/null and b/examples/c/ssl_certs/tserver-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/ssl_certs/tserver-certificate.pem
----------------------------------------------------------------------
diff --git a/examples/c/ssl_certs/tserver-certificate.pem 
b/examples/c/ssl_certs/tserver-certificate.pem
new file mode 100644
index 0000000..86231f3
--- /dev/null
+++ b/examples/c/ssl_certs/tserver-certificate.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDKzCCAhOgAwIBAgIJAPnYOOQCJ3kDMA0GCSqGSIb3DQEBCwUAMCwxFDASBgNV
+BAMMC3Rlc3Rfc2VydmVyMRQwEgYDVQQLDAtwcm90b25fdGVzdDAeFw0xNTExMjcx
+ODEwMzlaFw0yNTExMjQxODEwMzlaMCwxFDASBgNVBAMMC3Rlc3Rfc2VydmVyMRQw
+EgYDVQQLDAtwcm90b25fdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAKJNB78lgw4KtXDAvXocTLud6mbn6zgfB6ETIF+kcrukOH9DnPxjLBBM4Lig
+sp1+kmeudFK5/X8riDrvIW52b/rlEBLgLB+oDtI74m6OTbBs9L+FUFYOuxApetQF
+qoJy2vf9pWfy4uku24vCpeo7eVLi6ypu4lXE3LR+Km3FruHI1NKonHBMhwXSOWqF
+pYM6/4IZJ4fbV0+eU0Jrx+05s6XHg5vone2BVJKxeSIBje+zWnNnh8+qG0Z70Jgp
+aMetME5KGnLNgD1okpH0vb3lwjvuqkkx4WswGVZGbLLkSqqBpXPyM9fCFVy5aKSL
+DBq7IABQtO67O2nBzK3OyigHrUUCAwEAAaNQME4wHQYDVR0OBBYEFGV1PY0FCFbJ
+gpcDVKI6JGiRTt3kMB8GA1UdIwQYMBaAFGV1PY0FCFbJgpcDVKI6JGiRTt3kMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAIx1TOTGWnnbpan4bse7wuvH
+GYSNDJhoTVS+X1TC63xukJD1JBAsCNTqg/ZV6lN3XEl7vvOXfGoCiyXM6a9XOKUo
+gSDtMrIr+wTh6Ss1yRO8QcCJmxH5JDXNu1ojtwsjFW/vneI4IL9kwpDsSlMQEX/E
+EkkQwtAx/Cvfe7pecZL4qSeykJOUMTts9H8fCAZqEiRZBA3ugJxqF8jwLP3DoFVQ
+6QZzKDY6CSPqfMnVb5i0MAIYVDpau+e3N9dgQpZD22F/zbua0OVbfAPdiRMnYxML
+FT4sxLnh+5YVqwpVWbEKp4onHe2Fq6YIvAxUYAJ3SBA2C8O2RAVKWxf1jko3jYI=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/ssl_certs/tserver-full.p12
----------------------------------------------------------------------
diff --git a/examples/c/ssl_certs/tserver-full.p12 
b/examples/c/ssl_certs/tserver-full.p12
new file mode 100644
index 0000000..d4a0e40
Binary files /dev/null and b/examples/c/ssl_certs/tserver-full.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/examples/c/ssl_certs/tserver-private-key.pem
----------------------------------------------------------------------
diff --git a/examples/c/ssl_certs/tserver-private-key.pem 
b/examples/c/ssl_certs/tserver-private-key.pem
new file mode 100644
index 0000000..91dcf0e
--- /dev/null
+++ b/examples/c/ssl_certs/tserver-private-key.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI1cT0c2J3GcQCAggA
+MBQGCCqGSIb3DQMHBAi1hxSX2LJ+EgSCBMheHJ0iXr5A36Natjk/LcAEeKUMT9s+
+sMzoQceCWe8qMlQluWksr9iDdZ4JRIE8cpK8dbmx4dLY/SShUzdlhJHCSa4zZBHq
+8cZ/jGUF/RF1rqdgjK589eUq+uOl3/gXKzG/SxBqayy6PSn12kX3qnvmlkXCmtwU
+lg+iBm5wRcJ0MyVHaJkyA8sW8gr186C/VAau6Yu0crQXN7NRo9snrd4ewuYMIEhZ
+hgaG9XsYQWB1bPhAaKj80CZGxsQbJyTwcbKKkB3IY4WXx8mmhuiNl+vKT3HBJ9Ju
+YB6tgIjs8CJ4X2P4aU3yNJwG1QldgHSqmFGQ19bcZAw3s3kzwjdzRf4H2V16XOBd
+zQ5AEs/ffVMzMIAfkb1gYwgunZ2CVwwDJ2mi1RcgkX+Og2aFQc+fxXcVOnDcGLxV
+6fuCuZ2lsXfoiIyRh9kj3L75N12GtVUvgBdnMuOc1wPw6XnGQtDwt0acJpdexLMG
+k0j57r/gcgzTcmF3qNM+y9L/HLssgrJkvVJw2Np5gmtIyfDocsDUWUbClS4dTpYf
+oTngUTU+vWtHBuaUnb+f5/WJaRS/S7mmR8usbVG3i9WnEr/vlPJpbJFSjW2S6u/H
+7cFxKUmmBZsSuEv/EKt9a+Sh62kprOChm4myqfCI1/gvNKfUZC6m0Vp8zf+2LgAq
+2RgbMuqysMjWUtV4kDRZT7oCYckUDwsCHdbLES3nmVrtBk2ShMKHBpDp8/GoRuiV
+jdV7/EjKM/M1kXtFYYe3z7Mxv++lKYIJ7bNwVrQ8nrhce/VwHw6D5emWXNCJXhKZ
+FW7EM2ZOZ9eaKOlCsIi8sbjV6Yie9IY6HJKKmi3CpO0Tv5kLBdHkru8vGCSFm3O1
+n7wz7Ys5FBSlZ19X0NwQSCQX1Q4w+tido6i1SCRX0qJEdTNGuGwVXMHCf4/1zyHV
+hj8vnxh8fzo79LFrwlTTgwLg1Mr8sEUFFDJ/raJ1AhFXi8n24trtNR8EHxRW8wtD
+CLCKaqkEqfBiFXK/Yq3RrefCayPHiD+DaNsI8BwefMGpED3vD8YYCjAzXNPh/CSF
+sc1i1jWMzbJhzOoFSPNXhlfusbUFMFQ/6olatmH47SY6HBBOL3DDP5uQ0jw8P454
+QBjlMOpEZmZxO6TcEtJwu0vzgog4rQ5g3NWy6SIpjWehNwTynLt7yM3R5WTI6cZs
+0GTv/rqo2/SUoNsFmnGIUwj/DrBe4XOAq1nS2ZlEctxKhBsKH0hMFp6D1rXOzrgl
+bwcq+oistoB0TLcThShyNgSqzW1znQ1n5SVUk9b5rRhSttJxn3yOMewH0i3v8bPo
+HOhP5kaGjblPsCYyhlL/SNVF0OXEGTwLNey7FQdWFOwVwTRRXe7k+uGZ2d5hg+Jn
+It/trDZ1RDYbVmB7/Qy73c16J4mvhOUJ2de5ZciFBjkidbiiUKLj9xnjK9k9Sauo
+MKhNnDMAEU5VDQM3xNe5BRdX8dFLwfF5H64sU3nROF83aUnDgvfFEowYPnCuPYfm
+m4aQHfoBSg4j3v1OeOwktcl+Q2TjxPHfWhbWeRBfxOTqQ/suYhnQChuFSK/qyo9K
+ccgotqghhunRsWMoZT25H7AZM6yKb1sMz/0oyMRIKeGqoYh+ULM5XLY0xNYd4/xU
+WtQ=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/proton-c/src/ssl/openssl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/ssl/openssl.c b/proton-c/src/ssl/openssl.c
index 3929f88..f8479f0 100644
--- a/proton-c/src/ssl/openssl.c
+++ b/proton-c/src/ssl/openssl.c
@@ -57,11 +57,10 @@
  * This file contains an OpenSSL-based implemention of the SSL/TLS API.
  */
 
-static int ssl_initialized;
-static int ssl_ex_data_index;
-
 typedef struct pn_ssl_session_t pn_ssl_session_t;
 
+static int ssl_ex_data_index;
+
 struct pn_ssl_domain_t {
 
   SSL_CTX       *ctx;
@@ -119,14 +118,14 @@ struct pni_ssl_t {
 
 static inline pn_transport_t *get_transport_internal(pn_ssl_t *ssl)
 {
-    // The external pn_sasl_t is really a pointer to the internal 
pni_transport_t
-    return ((pn_transport_t *)ssl);
+  // The external pn_sasl_t is really a pointer to the internal pni_transport_t
+  return ((pn_transport_t *)ssl);
 }
 
 static inline pni_ssl_t *get_ssl_internal(pn_ssl_t *ssl)
 {
-    // The external pn_sasl_t is really a pointer to the internal 
pni_transport_t
-    return ssl ? ((pn_transport_t *)ssl)->ssl : NULL;
+  // The external pn_sasl_t is really a pointer to the internal pni_transport_t
+  return ssl ? ((pn_transport_t *)ssl)->ssl : NULL;
 }
 
 // define two sets of allowable ciphers: those that require authentication, 
and those
@@ -265,8 +264,8 @@ static bool match_dns_pattern( const char *hostname,
       int suffix_len = strlen(suffix);
       if (prefix_len && pn_strncasecmp( prefix, slabel, prefix_len )) return 
false;
       if (suffix_len && pn_strncasecmp( suffix,
-                                     slabel + (strlen(slabel) - suffix_len),
-                                     suffix_len )) return false;
+                                        slabel + (strlen(slabel) - suffix_len),
+                                        suffix_len )) return false;
     }
   }
 
@@ -348,7 +347,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX 
*ctx)
 
   if (!matched) {
     ssl_log(transport, "Error: no name matching %s found in peer cert - 
rejecting handshake.",
-          ssl->peer_hostname);
+            ssl->peer_hostname);
     preverify_ok = 0;
 #ifdef X509_V_ERR_APPLICATION_VERIFICATION
     X509_STORE_CTX_set_error( ctx, X509_V_ERR_APPLICATION_VERIFICATION );
@@ -477,18 +476,14 @@ bool pn_ssl_present(void)
   return true;
 }
 
+static bool ensure_initialized(void);
+
 pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
 {
-  if (!ssl_initialized) {
-    ssl_initialized = 1;
-    SSL_library_init();
-    SSL_load_error_strings();
-    OpenSSL_add_all_algorithms();
-    ssl_ex_data_index = SSL_get_ex_new_index( 0, (void *) 
"org.apache.qpid.proton.ssl",
-                                              NULL, NULL, NULL);
-    ssn_init();
+  if (!ensure_initialized()) {
+      ssl_log_error("Unable to initialize OpenSSL library");
+      return NULL;
   }
-
   pn_ssl_domain_t *domain = (pn_ssl_domain_t *) calloc(1, 
sizeof(pn_ssl_domain_t));
   if (!domain) return NULL;
 
@@ -499,7 +494,7 @@ pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
   // known vulnerable ones.  This should allow us to use the latest version
   // of the TLS standard that the installed library supports.
   switch(mode) {
-  case PN_SSL_MODE_CLIENT:
+   case PN_SSL_MODE_CLIENT:
     domain->ctx = SSL_CTX_new(SSLv23_client_method()); // and TLSv1+
     SSL_CTX_set_session_cache_mode(domain->ctx, SSL_SESS_CACHE_CLIENT);
     if (!domain->ctx) {
@@ -509,7 +504,7 @@ pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
     }
     break;
 
-  case PN_SSL_MODE_SERVER:
+   case PN_SSL_MODE_SERVER:
     domain->ctx = SSL_CTX_new(SSLv23_server_method()); // and TLSv1+
     if (!domain->ctx) {
       ssl_log_error("Unable to initialize OpenSSL context.");
@@ -518,7 +513,7 @@ pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
     }
     break;
 
-  default:
+   default:
     pn_transport_logf(NULL, "Invalid value for pn_ssl_mode_t: %d", mode);
     free(domain);
     return NULL;
@@ -530,7 +525,7 @@ pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
   SSL_CTX_set_options(domain->ctx, SSL_OP_NO_COMPRESSION);
 #endif
 #if OPENSSL_VERSION_NUMBER >= 0x10100000
-    domain->default_seclevel = SSL_CTX_get_security_level(domain->ctx);
+  domain->default_seclevel = SSL_CTX_get_security_level(domain->ctx);
 #endif
 
   // by default, allow anonymous ciphers so certificates are not required 'out 
of the box'
@@ -570,9 +565,9 @@ void pn_ssl_domain_free( pn_ssl_domain_t *domain )
 
 
 int pn_ssl_domain_set_credentials( pn_ssl_domain_t *domain,
-                               const char *certificate_file,
-                               const char *private_key_file,
-                               const char *password)
+                                   const char *certificate_file,
+                                   const char *private_key_file,
+                                   const char *password)
 {
   if (!domain || !domain->ctx) return -1;
 
@@ -594,7 +589,7 @@ int pn_ssl_domain_set_credentials( pn_ssl_domain_t *domain,
 
   if (SSL_CTX_check_private_key(domain->ctx) != 1) {
     ssl_log_error("The key file %s is not consistent with the certificate %s",
-                   private_key_file, certificate_file);
+                  private_key_file, certificate_file);
     return -5;
   }
 
@@ -604,8 +599,8 @@ int pn_ssl_domain_set_credentials( pn_ssl_domain_t *domain,
   // cipher was negotiated.  TLSv1 will reject such a request.  Hack: once a 
cert is
   // configured, allow only authenticated ciphers.
   if (!domain->ciphers && !SSL_CTX_set_cipher_list( domain->ctx, 
CIPHERS_AUTHENTICATE )) {
-      ssl_log_error("Failed to set cipher list to %s", CIPHERS_AUTHENTICATE);
-      return -6;
+    ssl_log_error("Failed to set cipher list to %s", CIPHERS_AUTHENTICATE);
+    return -6;
   }
 
   return 0;
@@ -664,8 +659,8 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t 
*domain,
   if (!domain) return -1;
 
   switch (mode) {
-  case PN_SSL_VERIFY_PEER:
-  case PN_SSL_VERIFY_PEER_NAME:
+   case PN_SSL_VERIFY_PEER:
+   case PN_SSL_VERIFY_PEER_NAME:
 
 #if OPENSSL_VERSION_NUMBER >= 0x10100000
     SSL_CTX_set_security_level(domain->ctx, domain->default_seclevel);
@@ -673,7 +668,7 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t 
*domain,
 
     if (!domain->has_ca_db) {
       pn_transport_logf(NULL, "Error: cannot verify peer without a trusted CA 
configured.\n"
-                 "       Use pn_ssl_domain_set_trusted_ca_db()");
+                        "       Use pn_ssl_domain_set_trusted_ca_db()");
       return -1;
     }
 
@@ -686,7 +681,7 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t 
*domain,
       }
       if (!domain->has_certificate) {
         pn_transport_logf(NULL, "Error: Server cannot verify peer without 
configuring a certificate.\n"
-                   "       Use pn_ssl_domain_set_credentials()");
+                          "       Use pn_ssl_domain_set_credentials()");
       }
 
       if (domain->trusted_CAs) free(domain->trusted_CAs);
@@ -708,7 +703,7 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t 
*domain,
 #endif
     break;
 
-  case PN_SSL_ANONYMOUS_PEER:   // hippie free love mode... :)
+   case PN_SSL_ANONYMOUS_PEER:   // hippie free love mode... :)
 #if OPENSSL_VERSION_NUMBER >= 0x10100000
     // Must use lowest OpenSSL security level to enable anonymous ciphers.
     SSL_CTX_set_security_level(domain->ctx, 0);
@@ -716,7 +711,7 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t 
*domain,
     SSL_CTX_set_verify( domain->ctx, SSL_VERIFY_NONE, NULL );
     break;
 
-  default:
+   default:
     pn_transport_logf(NULL, "Invalid peer authentication mode given." );
     return -1;
   }
@@ -726,35 +721,35 @@ int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t 
*domain,
 }
 
 const pn_io_layer_t ssl_layer = {
-    process_input_ssl,
-    process_output_ssl,
-    handle_error_ssl,
-    NULL,
-    buffered_output
+  process_input_ssl,
+  process_output_ssl,
+  handle_error_ssl,
+  NULL,
+  buffered_output
 };
 
 const pn_io_layer_t ssl_input_closed_layer = {
-    process_input_done,
-    process_output_ssl,
-    handle_error_ssl,
-    NULL,
-    buffered_output
+  process_input_done,
+  process_output_ssl,
+  handle_error_ssl,
+  NULL,
+  buffered_output
 };
 
 const pn_io_layer_t ssl_output_closed_layer = {
-    process_input_ssl,
-    process_output_done,
-    handle_error_ssl,
-    NULL,
-    buffered_output
+  process_input_ssl,
+  process_output_done,
+  handle_error_ssl,
+  NULL,
+  buffered_output
 };
 
 const pn_io_layer_t ssl_closed_layer = {
-    process_input_done,
-    process_output_done,
-    handle_error_ssl,
-    NULL,
-    buffered_output
+  process_input_done,
+  process_output_done,
+  handle_error_ssl,
+  NULL,
+  buffered_output
 };
 
 int pn_ssl_init(pn_ssl_t *ssl0, pn_ssl_domain_t *domain, const char 
*session_id)
@@ -886,9 +881,9 @@ pn_ssl_t *pn_ssl(pn_transport_t *transport)
 
 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));
+  strncpy(buf, (char *)userdata, size);   // @todo: un-obfuscate me!!!
+  buf[size - 1] = '\0';
+  return(strlen(buf));
 }
 
 
@@ -958,13 +953,13 @@ static ssize_t process_input_ssl( pn_transport_t 
*transport, unsigned int layer,
         if (!BIO_should_retry(ssl->bio_ssl)) {
           int reason = SSL_get_error( ssl->ssl, read );
           switch (reason) {
-          case SSL_ERROR_ZERO_RETURN:
+           case SSL_ERROR_ZERO_RETURN:
             // SSL closed cleanly
             ssl_log(transport, "SSL connection has closed");
             start_ssl_shutdown(transport);  // KAG: not sure - this may not be 
necessary
             ssl->ssl_closed = true;
             break;
-          default:
+           default:
             // unexpected error
             return (ssize_t)ssl_failed(transport);
           }
@@ -994,7 +989,7 @@ static ssize_t process_input_ssl( pn_transport_t 
*transport, unsigned int layer,
           ssl_log( transport, "Application consumed %d bytes from peer", (int) 
consumed );
         } else if (consumed < 0) {
           ssl_log(transport, "Application layer closed its input, error=%d 
(discarding %d bytes)",
-               (int) consumed, (int)ssl->in_count);
+                  (int) consumed, (int)ssl->in_count);
           ssl->in_count = 0;    // discard any pending input
           ssl->app_input_closed = consumed;
           if (ssl->app_output_closed && ssl->out_count == 0) {
@@ -1086,7 +1081,7 @@ static ssize_t process_output_ssl( pn_transport_t 
*transport, unsigned int layer
       } else {
         if (app_bytes < 0) {
           ssl_log(transport, "Application layer closed its output, error=%d 
(%d bytes pending send)",
-               (int) app_bytes, (int) ssl->out_count);
+                  (int) app_bytes, (int) ssl->out_count);
           ssl->app_output_closed = app_bytes;
         }
       }
@@ -1107,14 +1102,14 @@ static ssize_t process_output_ssl( pn_transport_t 
*transport, unsigned int layer
           if (!BIO_should_retry(ssl->bio_ssl)) {
             int reason = SSL_get_error( ssl->ssl, wrote );
             switch (reason) {
-            case SSL_ERROR_ZERO_RETURN:
+             case SSL_ERROR_ZERO_RETURN:
               // SSL closed cleanly
               ssl_log(transport, "SSL connection has closed");
               start_ssl_shutdown(transport); // KAG: not sure - this may not 
be necessary
               ssl->out_count = 0;      // can no longer write to socket, so 
erase app output data
               ssl->ssl_closed = true;
               break;
-            default:
+             default:
               // unexpected error
               return (ssize_t)ssl_failed(transport);
             }
@@ -1236,7 +1231,7 @@ static void release_ssl_socket(pni_ssl_t *ssl)
 {
   if (ssl->bio_ssl) BIO_free(ssl->bio_ssl);
   if (ssl->ssl) {
-      SSL_free(ssl->ssl);       // will free bio_ssl_io
+    SSL_free(ssl->ssl);       // will free bio_ssl_io
   } else {
     if (ssl->bio_ssl_io) BIO_free(ssl->bio_ssl_io);
   }
@@ -1254,9 +1249,9 @@ pn_ssl_resume_status_t pn_ssl_resume_status(pn_ssl_t 
*ssl0)
   pni_ssl_t *ssl = get_ssl_internal(ssl0);
   if (!ssl || !ssl->ssl) return PN_SSL_RESUME_UNKNOWN;
   switch (SSL_session_reused( ssl->ssl )) {
-  case 0: return PN_SSL_RESUME_NEW;
-  case 1: return PN_SSL_RESUME_REUSED;
-  default: break;
+   case 0: return PN_SSL_RESUME_NEW;
+   case 1: return PN_SSL_RESUME_REUSED;
+   default: break;
   }
   return PN_SSL_RESUME_UNKNOWN;
 }
@@ -1332,124 +1327,124 @@ const char* pn_ssl_get_remote_subject(pn_ssl_t *ssl0)
 
 int pn_ssl_get_cert_fingerprint(pn_ssl_t *ssl0, char *fingerprint, size_t 
fingerprint_length, pn_ssl_hash_alg hash_alg)
 {
-    const char *digest_name = NULL;
-    size_t min_required_length;
-
-    // old versions of python expect fingerprint to contain a valid string on
-    // return from this function
-    fingerprint[0] = 0;
-
-    // Assign the correct digest_name value based on the enum values.
-    switch (hash_alg) {
-        case PN_SSL_SHA1 :
-            min_required_length = 41; // 40 hex characters + 1 '\0' character
-            digest_name = "sha1";
-            break;
-        case PN_SSL_SHA256 :
-            min_required_length = 65; // 64 hex characters + 1 '\0' character
-            digest_name = "sha256";
-            break;
-        case PN_SSL_SHA512 :
-            min_required_length = 129; // 128 hex characters + 1 '\0' character
-            digest_name = "sha512";
-            break;
-        case PN_SSL_MD5 :
-            min_required_length = 33; // 32 hex characters + 1 '\0' character
-            digest_name = "md5";
-            break;
-        default:
-            ssl_log_error("Unknown or unhandled hash algorithm %i \n", 
hash_alg);
-            return PN_ERR;
-
-    }
+  const char *digest_name = NULL;
+  size_t min_required_length;
+
+  // old versions of python expect fingerprint to contain a valid string on
+  // return from this function
+  fingerprint[0] = 0;
+
+  // Assign the correct digest_name value based on the enum values.
+  switch (hash_alg) {
+   case PN_SSL_SHA1 :
+    min_required_length = 41; // 40 hex characters + 1 '\0' character
+    digest_name = "sha1";
+    break;
+   case PN_SSL_SHA256 :
+    min_required_length = 65; // 64 hex characters + 1 '\0' character
+    digest_name = "sha256";
+    break;
+   case PN_SSL_SHA512 :
+    min_required_length = 129; // 128 hex characters + 1 '\0' character
+    digest_name = "sha512";
+    break;
+   case PN_SSL_MD5 :
+    min_required_length = 33; // 32 hex characters + 1 '\0' character
+    digest_name = "md5";
+    break;
+   default:
+    ssl_log_error("Unknown or unhandled hash algorithm %i \n", hash_alg);
+    return PN_ERR;
 
-    if(fingerprint_length < min_required_length) {
-        ssl_log_error("Insufficient fingerprint_length %i. fingerprint_length 
must be %i or above for %s digest\n",
-            fingerprint_length, min_required_length, digest_name);
-        return PN_ERR;
-    }
+  }
 
-    const EVP_MD  *digest = EVP_get_digestbyname(digest_name);
+  if(fingerprint_length < min_required_length) {
+    ssl_log_error("Insufficient fingerprint_length %i. fingerprint_length must 
be %i or above for %s digest\n",
+                  fingerprint_length, min_required_length, digest_name);
+    return PN_ERR;
+  }
 
-    pni_ssl_t *ssl = get_ssl_internal(ssl0);
-    X509 *cert = get_peer_certificate(ssl);
+  const EVP_MD  *digest = EVP_get_digestbyname(digest_name);
 
-    if(cert) {
-        unsigned int len;
+  pni_ssl_t *ssl = get_ssl_internal(ssl0);
+  X509 *cert = get_peer_certificate(ssl);
 
-        unsigned char bytes[64]; // sha512 uses 64 octets, we will use that as 
the maximum.
+  if(cert) {
+    unsigned int len;
 
-        if (X509_digest(cert, digest, bytes, &len) != 1) {
-            ssl_log_error("Failed to extract X509 digest\n");
-            return PN_ERR;
-       }
+    unsigned char bytes[64]; // sha512 uses 64 octets, we will use that as the 
maximum.
 
-        char *cursor = fingerprint;
+    if (X509_digest(cert, digest, bytes, &len) != 1) {
+      ssl_log_error("Failed to extract X509 digest\n");
+      return PN_ERR;
+    }
 
-        for (size_t i=0; i<len ; i++) {
-            cursor +=  pni_snprintf((char *)cursor, fingerprint_length, 
"%02x", bytes[i]);
-            fingerprint_length = fingerprint_length - 2;
-        }
+    char *cursor = fingerprint;
 
-        return PN_OK;
-    }
-    else {
-        ssl_log_error("No certificate is available yet \n");
-        return PN_ERR;
+    for (size_t i=0; i<len ; i++) {
+      cursor +=  pni_snprintf((char *)cursor, fingerprint_length, "%02x", 
bytes[i]);
+      fingerprint_length = fingerprint_length - 2;
     }
 
-    return 0;
+    return PN_OK;
+  }
+  else {
+    ssl_log_error("No certificate is available yet \n");
+    return PN_ERR;
+  }
+
+  return 0;
 }
 
 
 const char* pn_ssl_get_remote_subject_subfield(pn_ssl_t *ssl0, 
pn_ssl_cert_subject_subfield field)
 {
-    int openssl_field = 0;
+  int openssl_field = 0;
 
-    // Assign openssl internal representations of field values to openssl_field
-    switch (field) {
-        case PN_SSL_CERT_SUBJECT_COUNTRY_NAME :
-            openssl_field = NID_countryName;
-            break;
-        case PN_SSL_CERT_SUBJECT_STATE_OR_PROVINCE :
-            openssl_field = NID_stateOrProvinceName;
-            break;
-        case PN_SSL_CERT_SUBJECT_CITY_OR_LOCALITY :
-            openssl_field = NID_localityName;
-            break;
-        case PN_SSL_CERT_SUBJECT_ORGANIZATION_NAME :
-            openssl_field = NID_organizationName;
-            break;
-        case PN_SSL_CERT_SUBJECT_ORGANIZATION_UNIT :
-            openssl_field = NID_organizationalUnitName;
-            break;
-        case PN_SSL_CERT_SUBJECT_COMMON_NAME :
-            openssl_field = NID_commonName;
-            break;
-        default:
-            ssl_log_error("Unknown or unhandled certificate subject subfield 
%i \n", field);
-            return NULL;
-    }
+  // Assign openssl internal representations of field values to openssl_field
+  switch (field) {
+   case PN_SSL_CERT_SUBJECT_COUNTRY_NAME :
+    openssl_field = NID_countryName;
+    break;
+   case PN_SSL_CERT_SUBJECT_STATE_OR_PROVINCE :
+    openssl_field = NID_stateOrProvinceName;
+    break;
+   case PN_SSL_CERT_SUBJECT_CITY_OR_LOCALITY :
+    openssl_field = NID_localityName;
+    break;
+   case PN_SSL_CERT_SUBJECT_ORGANIZATION_NAME :
+    openssl_field = NID_organizationName;
+    break;
+   case PN_SSL_CERT_SUBJECT_ORGANIZATION_UNIT :
+    openssl_field = NID_organizationalUnitName;
+    break;
+   case PN_SSL_CERT_SUBJECT_COMMON_NAME :
+    openssl_field = NID_commonName;
+    break;
+   default:
+    ssl_log_error("Unknown or unhandled certificate subject subfield %i \n", 
field);
+    return NULL;
+  }
 
-    pni_ssl_t *ssl = get_ssl_internal(ssl0);
-    X509 *cert = get_peer_certificate(ssl);
-    if (!cert) return NULL;
+  pni_ssl_t *ssl = get_ssl_internal(ssl0);
+  X509 *cert = get_peer_certificate(ssl);
+  if (!cert) return NULL;
 
-    X509_NAME *subject_name = X509_get_subject_name(cert);
+  X509_NAME *subject_name = X509_get_subject_name(cert);
 
-    // TODO (gmurthy) - A server side cert subject field can have more than 
one common name like this - Subject: CN=www.domain1.com, CN=www.domain2.com, 
see https://bugzilla.mozilla.org/show_bug.cgi?id=380656
-    // For now, we will only return the first common name if there is more 
than one common name in the cert
-    int index = X509_NAME_get_index_by_NID(subject_name, openssl_field, -1);
+  // TODO (gmurthy) - A server side cert subject field can have more than one 
common name like this - Subject: CN=www.domain1.com, CN=www.domain2.com, see 
https://bugzilla.mozilla.org/show_bug.cgi?id=380656
+  // For now, we will only return the first common name if there is more than 
one common name in the cert
+  int index = X509_NAME_get_index_by_NID(subject_name, openssl_field, -1);
 
-    if (index > -1) {
-        X509_NAME_ENTRY *ne = X509_NAME_get_entry(subject_name, index);
-        if(ne) {
-            ASN1_STRING *name_asn1 = X509_NAME_ENTRY_get_data(ne);
-            return (char *) name_asn1->data;
-        }
+  if (index > -1) {
+    X509_NAME_ENTRY *ne = X509_NAME_get_entry(subject_name, index);
+    if(ne) {
+      ASN1_STRING *name_asn1 = X509_NAME_ENTRY_get_data(ne);
+      return (char *) name_asn1->data;
     }
+  }
 
-    return NULL;
+  return NULL;
 }
 
 static ssize_t process_input_done(pn_transport_t *transport, unsigned int 
layer, const char *input_data, size_t len)
@@ -1474,3 +1469,88 @@ static size_t buffered_output(pn_transport_t *transport)
   }
   return count;
 }
+
+
+/* Thread-safe locking and initialization for POSIX and Windows */
+
+static bool init_ok = false;
+
+#ifdef _WIN32
+
+typedef CRITICAL_SECTION pni_mutex_t;
+static inline void pni_mutex_init(pni_mutex_t *m) { 
InitializeCriticalSection(m); }
+static inline void pni_mutex_lock(pni_mutex_t *m) { EnterCriticalSection(m); }
+static inline void pni_mutex_unlock(pni_mutex_t *m) { LeaveCriticalSection(m); 
}
+static inline unsigned long id_callback(void) { return (unsigned 
long)GetCurrentThreadId(); }
+INIT_ONCE initialize_once = INIT_ONCE_STATIC_INIT;
+static inline bool ensure_initialized(void) {
+  void* dummy;
+  InitOnceExecuteOnce(&initialize_once, &initialize, NULL, &dummy);
+  return init_ok;
+}
+
+#else  /* POSIX */
+
+#include <pthread.h>
+
+static void initialize(void);
+
+typedef pthread_mutex_t pni_mutex_t;
+static inline int pni_mutex_init(pni_mutex_t *m) { return 
pthread_mutex_init(m, NULL); }
+static inline int pni_mutex_lock(pni_mutex_t *m) { return 
pthread_mutex_lock(m); }
+static inline int pni_mutex_unlock(pni_mutex_t *m) { return 
pthread_mutex_unlock(m); }
+static inline unsigned long id_callback(void) { return (unsigned 
long)pthread_self(); }
+static pthread_once_t initialize_once = PTHREAD_ONCE_INIT;
+static inline bool ensure_initialized(void) {
+  pthread_once(&initialize_once, &initialize);
+  return init_ok;
+}
+
+#endif
+
+static pni_mutex_t *locks = NULL;     /* Lock array for openssl */
+
+/* Callback function for openssl locking */
+static void locking_callback(int mode, int n, const char *file, int line) {
+  if(mode & CRYPTO_LOCK)
+    pni_mutex_lock(&locks[n]);
+  else
+    pni_mutex_unlock(&locks[n]);
+}
+
+static void initialize(void) {
+  int i;
+  SSL_library_init();
+  SSL_load_error_strings();
+  OpenSSL_add_all_algorithms();
+  ssl_ex_data_index = SSL_get_ex_new_index( 0, (void *) 
"org.apache.qpid.proton.ssl",
+                                            NULL, NULL, NULL);
+  ssn_init();
+  locks = (pni_mutex_t*)malloc(CRYPTO_num_locks() * sizeof(pni_mutex_t));
+  if (!locks) return;
+  for(i = 0;  i < CRYPTO_num_locks();  i++)
+    pni_mutex_init(&locks[i]);
+  CRYPTO_set_id_callback(&id_callback);
+  CRYPTO_set_locking_callback(&locking_callback);
+  /* In recent versions of openssl, the set_callback functions are no-op 
macros,
+     so we need to take steps to stop the compiler complaining about unused 
functions. */
+  (void)&id_callback;
+  (void)&locking_callback;
+  init_ok = true;
+}
+
+/* TODO aconway 2017-10-16: There is no opportunity to clean up the locks as 
proton has no
+   final shut-down call. If it did, we should call this: */
+/*
+static void shutdown(void) {
+  CRYPTO_set_id_callback(NULL);
+  CRYPTO_set_locking_callback(NULL);
+  if(locks)  {
+    int i;
+    for(i = 0;  i < CRYPTO_num_locks();  i++)
+      pni_mutex_destroy(&locks[i]);
+    free(locks);
+    locks = NULL;
+  }
+}
+*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/434a2e77/proton-c/src/tests/proactor.c
----------------------------------------------------------------------
diff --git a/proton-c/src/tests/proactor.c b/proton-c/src/tests/proactor.c
index 5f84bfe..a0b2a15 100644
--- a/proton-c/src/tests/proactor.c
+++ b/proton-c/src/tests/proactor.c
@@ -686,7 +686,6 @@ static void test_release_free(test_t *t) {
 #  define CERTIFICATE(NAME) SSL_FILE(NAME "-certificate.p12")
 #  define SET_CREDENTIALS(DOMAIN, NAME)                                 \
   pn_ssl_domain_set_credentials(DOMAIN, SSL_FILE(NAME "-full.p12"), "", SSL_PW)
-
 #else
 #  define CERTIFICATE(NAME) SSL_FILE(NAME "-certificate.pem")
 #  define SET_CREDENTIALS(DOMAIN, NAME)                                 \


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

Reply via email to