summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Mesnier <mesnier_p@ociweb.com>2015-03-10 15:46:59 -0500
committerPhil Mesnier <mesnier_p@ociweb.com>2015-03-10 15:46:59 -0500
commita4f928e8bf747aa2d20f7c367b3fd6beb078345b (patch)
treeac08ef9b61624fe811ebae115fa738b48347c795
parentd91af284f8ce1f723c1e242c31188c734999d1f1 (diff)
downloadATCD-a4f928e8bf747aa2d20f7c367b3fd6beb078345b.tar.gz
Improve robustness of version limiting method. Add a new method for verifying the peer host name matches the supplied certificate.
-rw-r--r--ACE/ace/SSL/SSL_Context.cpp109
-rw-r--r--ACE/ace/SSL/SSL_Context.h5
2 files changed, 103 insertions, 11 deletions
diff --git a/ACE/ace/SSL/SSL_Context.cpp b/ACE/ace/SSL/SSL_Context.cpp
index 3a2cfc8c124..1dfaf5cbed1 100644
--- a/ACE/ace/SSL/SSL_Context.cpp
+++ b/ACE/ace/SSL/SSL_Context.cpp
@@ -13,8 +13,10 @@
#include "ace/Synch_Traits.h"
#include "ace/Truncate.h"
#include "ace/ACE.h"
+#include "ace/INET_Addr.h"
#include "ace/OS_NS_errno.h"
#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_ctype.h"
#ifdef ACE_HAS_THREADS
# include "ace/Thread_Mutex.h"
@@ -22,6 +24,7 @@
#endif /* ACE_HAS_THREADS */
#include <openssl/x509.h>
+#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/safestack.h>
@@ -322,41 +325,125 @@ ACE_SSL_Context::filter_versions (const char* versionlist)
{
this->check_context ();
- ACE_CString ssl_versions = versionlist;
+ ACE_CString vlist = versionlist;
+ ACE_CString seplist = " ,;";
+ ACE_CString::size_type pos = 0;
+ bool match = false;
+
+ for (; pos < vlist.length (); pos++)
+ {
+ vlist[pos] = ACE_OS::ace_tolower (vlist[pos]);
+ }
#if defined (SSL_OP_NO_SSLv2)
- if (ssl_versions.find("SSLv2") == ACE_CString::npos)
+ pos = vlist.find("sslv2");
+ match = pos != ACE_CString::npos &&
+ (pos == vlist.length () - 5 ||
+ seplist.find (vlist[pos + 5]) != ACE_CString::npos);
+ if (!match)
{
- ::SSL_CTX_set_options(this->context_, SSL_OP_NO_SSLv2);
+ ::SSL_CTX_set_options (this->context_, SSL_OP_NO_SSLv2);
}
#endif /* SSL_OP_NO_SSLv2 */
+
#if defined (SSL_OP_NO_SSLv3)
- if (ssl_versions.find("SSLv3") == ACE_CString::npos)
+ pos = vlist.find("sslv3");
+ match = pos != ACE_CString::npos &&
+ (pos == vlist.length () - 5 ||
+ seplist.find (vlist[pos + 5]) != ACE_CString::npos);
+ if (!match)
{
- ::SSL_CTX_set_options(this->context_, SSL_OP_NO_SSLv3);
+ ::SSL_CTX_set_options (this->context_, SSL_OP_NO_SSLv3);
}
#endif /* SSL_OP_NO_SSLv3 */
+
#if defined (SSL_OP_NO_TLSv1)
- if (ssl_versions.find("TLSv1") == ACE_CString::npos)
+ pos = vlist.find("tlsv1");
+ match = pos != ACE_CString::npos &&
+ (pos == vlist.length () - 5 ||
+ seplist.find (vlist[pos + 5]) != ACE_CString::npos);
+ if (!match)
{
- ::SSL_CTX_set_options(this->context_, SSL_OP_NO_TLSv1);
+ ::SSL_CTX_set_options (this->context_, SSL_OP_NO_TLSv1);
}
#endif /* SSL_OP_NO_TLSv1 */
+
#if defined (SSL_OP_NO_TLSv1_1)
- if (ssl_versions.find("TLSv1.1") == ACE_CString::npos)
+ pos = vlist.find("tlsv1.1");
+ match = pos != ACE_CString::npos &&
+ (pos == vlist.length () - 7 ||
+ seplist.find (vlist[pos + 7]) != ACE_CString::npos);
+ if (!match)
{
- ::SSL_CTX_set_options(this->context_, SSL_OP_NO_TLSv1_1);
+ ::SSL_CTX_set_options (this->context_, SSL_OP_NO_TLSv1_1);
}
#endif /* SSL_OP_NO_TLSv1_1 */
+
#if defined (SSL_OP_NO_TLSv1_2)
- if (ssl_versions.find("TLSv1.2") == ACE_CString::npos)
+ pos = vlist.find("tlsv1.2");
+ match = pos != ACE_CString::npos &&
+ (pos == vlist.length () - 7 ||
+ seplist.find (vlist[pos + 7]) != ACE_CString::npos);
+ if (!match)
{
- ::SSL_CTX_set_options(this->context_, SSL_OP_NO_TLSv1_2);
+ ::SSL_CTX_set_options (this->context_, SSL_OP_NO_TLSv1_2);
}
#endif /* SSL_OP_NO_TLSv1_2 */
return 0;
}
+
+bool
+ACE_SSL_Context::check_host (const ACE_INET_Addr &host, SSL *peerssl)
+{
+#if defined (OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10002001L)
+
+ this->check_context ();
+
+ int result = 0;
+ char name[MAXHOSTNAMELEN+1];
+
+ if (peerssl == 0 || host.get_host_name (name, MAXHOSTNAMELEN) == -1)
+ {
+ return false;
+ }
+
+ X509* cert = ::SSL_get_peer_certificate (peerssl);
+ if (cert == 0)
+ {
+ return false;
+ }
+
+ char *peer = 0;
+ char **peerarg = ACE::debug () ? &peer : 0;
+ int flags = X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT;
+ size_t len = ACE_OS::strlen (name);
+
+ result = ::X509_check_host (cert, name, len, flags, peerarg);
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SSL_Context::check_host ")
+ ACE_TEXT ("name <%s> returns %d, peer <%s>\n"),
+ name, result, peer));
+ }
+ if (peer != 0)
+ {
+ ::OPENSSL_free (peer);
+ }
+
+ ::X509_free (cert);
+
+ return result == 1;
+#else
+ ACE_UNUSED_ARG (host);
+ ACE_UNUSED_ARG (peerssl);
+
+ return false;
+#endif /* OPENSSL_VERSION_NUMBER */
+}
+
int
ACE_SSL_Context::load_trusted_ca (const char* ca_file,
const char* ca_dir,
diff --git a/ACE/ace/SSL/SSL_Context.h b/ACE/ace/SSL/SSL_Context.h
index 85648042421..9dc1958ff59 100644
--- a/ACE/ace/SSL/SSL_Context.h
+++ b/ACE/ace/SSL/SSL_Context.h
@@ -29,6 +29,8 @@
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_INET_Addr;
+
class ACE_SSL_Export ACE_SSL_Data_File
{
public:
@@ -183,6 +185,9 @@ public:
/// Parse the string and filter crypto versions accordingly
int filter_versions (const char *filter);
+ /// verify the peer cert matches the host
+ bool check_host (const ACE_INET_Addr& host, SSL * peerssl);
+
/**
* Load the location of the trusted certification authority
* certificates. Note that CA certificates are stored in PEM format