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]