Author: kgiusti
Date: Fri Dec 14 19:18:02 2012
New Revision: 1422048

URL: http://svn.apache.org/viewvc?rev=1422048&view=rev
Log:
PROTON-161: make peer hostname setting a property, add new validation mode

Modified:
    qpid/proton/trunk/proton-c/bindings/python/proton.py
    qpid/proton/trunk/proton-c/bindings/python/python.i
    qpid/proton/trunk/proton-c/include/proton/ssl.h
    qpid/proton/trunk/proton-c/src/ssl/openssl.c
    qpid/proton/trunk/proton-c/src/ssl/ssl_stub.c
    qpid/proton/trunk/tests/proton_tests/ssl.py

Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1422048&r1=1422047&r2=1422048&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
+++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Dec 14 19:18:02 
2012
@@ -2342,6 +2342,7 @@ class SSL(object):
     return self._check( pn_ssl_allow_unsecured_client(self._ssl) )
 
   VERIFY_PEER = PN_SSL_VERIFY_PEER
+  VERIFY_PEER_NAME = PN_SSL_VERIFY_PEER_NAME
   ANONYMOUS_PEER = PN_SSL_ANONYMOUS_PEER
 
   def set_peer_authentication(self, verify_mode, trusted_CAs=None):
@@ -2364,8 +2365,16 @@ class SSL(object):
       return name
     return None
 
-  def set_peer_hostname(self, hostname, check=True):
-    pn_ssl_set_peer_hostname( self._ssl, hostname, check )
+  def _set_peer_hostname(self, hostname):
+    self._check(pn_ssl_set_peer_hostname( self._ssl, hostname ))
+  def _get_peer_hostname(self):
+    err, name = pn_ssl_get_peer_hostname( self._ssl, 1024 )
+    self._check(err)
+    return name
+  peer_hostname = property(_get_peer_hostname, _set_peer_hostname,
+                           doc="""
+Manage the expected name of the remote peer.  Used to authenticate the remote.
+""")
 
 __all__ = ["Messenger", "Message", "ProtonException", "MessengerException",
            "MessageException", "Timeout", "Condition", "Data", "Endpoint",

Modified: qpid/proton/trunk/proton-c/bindings/python/python.i
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/python.i?rev=1422048&r1=1422047&r2=1422048&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/python/python.i (original)
+++ qpid/proton/trunk/proton-c/bindings/python/python.i Fri Dec 14 19:18:02 2012
@@ -418,5 +418,8 @@ bool pn_ssl_get_cipher_name(pn_ssl_t *ss
 bool pn_ssl_get_protocol_name(pn_ssl_t *ssl, char *OUTPUT, size_t 
MAX_OUTPUT_SIZE);
 %ignore pn_ssl_get_protocol_name;
 
+int pn_ssl_get_peer_hostname(pn_ssl_t *ssl, char *OUTPUT, size_t *OUTPUT_SIZE);
+%ignore pn_ssl_get_peer_hostname;
+
 
 %include "proton/cproton.i"

Modified: qpid/proton/trunk/proton-c/include/proton/ssl.h
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/ssl.h?rev=1422048&r1=1422047&r2=1422048&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/ssl.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/ssl.h Fri Dec 14 19:18:02 2012
@@ -130,11 +130,15 @@ int pn_ssl_allow_unsecured_client(pn_ssl
 
 /** Determines the level of peer validation.
  *
- *  VERIFY_PEER will only connect to those peers that provide a valid 
identifying
- *  certificate signed by a trusted CA and are using an authenticated cipher.
  *  ANONYMOUS_PEER does not require a valid certificate, and permits use of 
ciphers that
  *  do not provide authentication.
  *
+ *  VERIFY_PEER will only connect to those peers that provide a valid 
identifying
+ *  certificate signed by a trusted CA and are using an authenticated cipher.
+ *
+ *  VERIFY_PEER_NAME is like VERIFY_PEER, but also requires the peer's 
identity as
+ *  contained in the certificate to be valid (see ::pn_ssl_set_peer_hostname).
+ *
  *  ANONYMOUS_PEER is configured by default.
  *
  *  These settings can be changed via ::pn_ssl_set_peer_authentication()
@@ -142,6 +146,7 @@ int pn_ssl_allow_unsecured_client(pn_ssl
 typedef enum {
   PN_SSL_VERIFY_PEER,     /**< require peer to provide a valid certificate */
   PN_SSL_ANONYMOUS_PEER,  /**< do not require a certificate nor cipher 
authorization */
+  PN_SSL_VERIFY_PEER_NAME,/**< require valid certificate and matching name */
 } pn_ssl_verify_mode_t;
 
 
@@ -212,26 +217,39 @@ bool pn_ssl_get_cipher_name(pn_ssl_t *ss
 bool pn_ssl_get_protocol_name(pn_ssl_t *ssl, char *buffer, size_t size);
 
 
-/** Set the DNS name of the server that the client expects to authenticate.
+/** Set the expected identity of the remote peer.
  *
- * Setting this name causes the client to 1) send this name to the server 
during the
- * handshake (if Server Name Indication is supported), and 2) check this name 
against the
- * identifying name provided in the server's certificate. If the supplied name 
does not
- * exactly match a SubjectAltName (type DNS name), or the CommonName entry in 
the server's
- * certificate, the server is considered unauthenticated, and the SSL 
connection is
- * aborted.
+ * The hostname is used for two purposes: 1) when set on an SSL client, it is 
sent to the
+ * server during the handshake (if Server Name Indication is supported), and 
2) it is used
+ * to check against the identifying name provided in the peer's certificate. 
If the
+ * supplied name does not exactly match a SubjectAltName (type DNS name), or 
the
+ * CommonName entry in the peer's certificate, the peer is considered 
unauthenticated
+ * (potential imposter), and the SSL connection is aborted.
  *
- * @note Verification of the hostname is only done if PN_SSL_VERIFY_PEER is 
enabled.
+ * @note Verification of the hostname is only done if PN_SSL_VERIFY_PEER_NAME 
is enabled.
  * See ::pn_ssl_set_peer_authentication.
  *
- * @param[in] ssl the ssl client
- * @param[in] hostname the value to check against the peer's CommonName field. 
 Expected
- * to conform to the syntax as given in RFC1034, Section 3.5.
- * @param[in] check_cert - if true, check hostname against the SubjectAltName 
(dns) or the
- * CommonName fields in the peer's certificate.  If no match is found, reject 
the
- * connection.
+ * @param[in] ssl the ssl session.
+ * @param[in] hostname the expected identity of the remote. Must conform to 
the syntax as
+ * given in RFC1034, Section 3.5.
+ * @return 0 on success.
+ */
+int pn_ssl_set_peer_hostname( pn_ssl_t *ssl, const char *hostname);
+
+
+/** Access the configured peer identity.
+ *
+ * Return the expected identity of the remote peer, as set by 
::pn_ssl_set_peer_hostname.
+ *
+ * @param[in] ssl the ssl session.
+ * @param[out] hostname buffer to hold the null-terminated name string. If 
null, no string
+ * is written.
+ * @param[in,out] bufsize on input set to the number of octets in hostname. On 
output, set
+ * to the number of octets needed to hold the value of hostname plus a null 
byte.  Zero if
+ * no hostname set.
+ * @return 0 on success.
  */
-void pn_ssl_set_peer_hostname( pn_ssl_t *ssl, const char *hostname, bool 
check_cert );
+int pn_ssl_get_peer_hostname( pn_ssl_t *ssl, char *hostname, size_t *bufsize );
 
 #ifdef __cplusplus
 }

Modified: qpid/proton/trunk/proton-c/src/ssl/openssl.c
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/ssl/openssl.c?rev=1422048&r1=1422047&r2=1422048&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/ssl/openssl.c (original)
+++ qpid/proton/trunk/proton-c/src/ssl/openssl.c Fri Dec 14 19:18:02 2012
@@ -56,9 +56,7 @@ struct pn_ssl_t {
   char *keyfile_pw;
   pn_ssl_verify_mode_t verify_mode;
   char *trusted_CAs;
-
   const char *peer_hostname;
-  bool check_cert_host; // if true: check hostname in cert.
 
   pn_transport_t *transport;
 
@@ -244,7 +242,11 @@ static int verify_callback(int preverify
     return 0;  // fail connection
   }
 
-  if (!ssl->peer_hostname || !ssl->check_cert_host) return preverify_ok;
+  if (ssl->verify_mode != PN_SSL_VERIFY_PEER_NAME) return preverify_ok;
+  if (!ssl->peer_hostname) {
+    _log_error("Error: configuration error: PN_SSL_VERIFY_PEER_NAME 
configured, but no peer hostname set!\n");
+    return 0;  // fail connection
+  }
 
   _log( ssl, "Checking identifying name in peer cert against '%s'\n", 
ssl->peer_hostname);
 
@@ -464,6 +466,7 @@ int pn_ssl_set_peer_authentication(pn_ss
 
   switch (mode) {
   case PN_SSL_VERIFY_PEER:
+  case PN_SSL_VERIFY_PEER_NAME:
 
     if (!ssl->has_ca_db) {
       _log_error("Error: cannot verify peer without a trusted CA configured.\n"
@@ -976,7 +979,7 @@ static int init_ssl_socket( pn_ssl_t *ss
   SSL_set_ex_data(ssl->ssl, ssl_ex_data_index, ssl);
 
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-  if (ssl->peer_hostname) {
+  if (ssl->peer_hostname && ssl->mode == PN_SSL_MODE_CLIENT) {
     SSL_set_tlsext_host_name(ssl->ssl, ssl->peer_hostname);
   }
 #endif
@@ -1113,20 +1116,38 @@ void pn_ssl_trace(pn_ssl_t *ssl, pn_trac
   ssl->trace = trace;
 }
 
-void pn_ssl_set_peer_hostname( pn_ssl_t *ssl, const char *hostname, bool 
check_cert)
+int pn_ssl_set_peer_hostname( pn_ssl_t *ssl, const char *hostname )
 {
-  if (!ssl) return;
+  if (!ssl) return -1;
 
   if (ssl->peer_hostname) free((void *)ssl->peer_hostname);
   ssl->peer_hostname = NULL;
-  ssl->check_cert_host = false;
   if (hostname) {
     ssl->peer_hostname = pn_strdup(hostname);
-    ssl->check_cert_host = check_cert;
+    if (!ssl->peer_hostname) return -2;
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-    if (ssl->ssl) {
+    if (ssl->ssl && ssl->mode == PN_SSL_MODE_CLIENT) {
       SSL_set_tlsext_host_name(ssl->ssl, ssl->peer_hostname);
     }
 #endif
   }
+  return 0;
+}
+
+int pn_ssl_get_peer_hostname( pn_ssl_t *ssl, char *hostname, size_t *bufsize )
+{
+  if (!ssl) return -1;
+  if (!ssl->peer_hostname) {
+    *bufsize = 0;
+    if (hostname) *hostname = '\0';
+    return 0;
+  }
+  int len = strlen(ssl->peer_hostname);
+  if (hostname) {
+    if (len >= *bufsize) return -1;
+    strcpy( hostname, ssl->peer_hostname );
+  }
+  *bufsize = len;
+  return 0;
 }
+

Modified: qpid/proton/trunk/proton-c/src/ssl/ssl_stub.c
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/ssl/ssl_stub.c?rev=1422048&r1=1422047&r2=1422048&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/ssl/ssl_stub.c (original)
+++ qpid/proton/trunk/proton-c/src/ssl/ssl_stub.c Fri Dec 14 19:18:02 2012
@@ -104,3 +104,12 @@ bool pn_ssl_get_protocol_name(pn_ssl_t *
   return false;
 }
 
+int pn_ssl_set_peer_hostname( pn_ssl_t *ssl, const char *hostname)
+{
+  return -1;
+}
+
+int pn_ssl_get_peer_hostname( pn_ssl_t *ssl, char *hostname, size_t *bufsize )
+{
+  return -1;
+}

Modified: qpid/proton/trunk/tests/proton_tests/ssl.py
URL: 
http://svn.apache.org/viewvc/qpid/proton/trunk/tests/proton_tests/ssl.py?rev=1422048&r1=1422047&r2=1422048&view=diff
==============================================================================
--- qpid/proton/trunk/tests/proton_tests/ssl.py (original)
+++ qpid/proton/trunk/tests/proton_tests/ssl.py Fri Dec 14 19:18:02 2012
@@ -287,8 +287,9 @@ class SslTest(common.Test):
 
         #self.t_client.trace( Transport.TRACE_DRV )
         self.client.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client.set_peer_authentication( SSL.VERIFY_PEER )
-        self.client.set_peer_hostname( "a1.good.server.domain.com" )
+        self.client.set_peer_authentication( SSL.VERIFY_PEER_NAME )
+        self.client.peer_hostname = "a1.good.server.domain.com"
+        assert self.client.peer_hostname == "a1.good.server.domain.com"
 
         client_conn = Connection()
         self.t_client.bind(client_conn)
@@ -312,8 +313,8 @@ class SslTest(common.Test):
 
         #self.t_client.trace( Transport.TRACE_DRV )
         self.client.set_trusted_ca_db(self._testpath("ca-certificate.pem"))
-        self.client.set_peer_authentication( SSL.VERIFY_PEER )
-        self.client.set_peer_hostname( "A1.Good.Server.domain.comx" )
+        self.client.set_peer_authentication( SSL.VERIFY_PEER_NAME )
+        self.client.peer_hostname = "A1.Good.Server.domain.comx"
 
         client_conn = Connection()
         self.t_client.bind(client_conn)



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to