aboutsummaryrefslogtreecommitdiffstats
path: root/src/security
diff options
context:
space:
mode:
Diffstat (limited to 'src/security')
-rw-r--r--src/security/cert/defaultCertificateVerifier.cpp15
-rw-r--r--src/security/cert/gnutls/X509Certificate_GnuTLS.cpp6
-rwxr-xr-xsrc/security/cert/openssl/X509Certificate_OpenSSL.cpp68
-rw-r--r--src/security/sasl/SASLSocket.cpp12
4 files changed, 98 insertions, 3 deletions
diff --git a/src/security/cert/defaultCertificateVerifier.cpp b/src/security/cert/defaultCertificateVerifier.cpp
index 6fde5519..65f5f476 100644
--- a/src/security/cert/defaultCertificateVerifier.cpp
+++ b/src/security/cert/defaultCertificateVerifier.cpp
@@ -50,7 +50,8 @@ defaultCertificateVerifier::defaultCertificateVerifier(const defaultCertificateV
}
-void defaultCertificateVerifier::verify(ref <certificateChain> chain)
+void defaultCertificateVerifier::verify
+ (ref <certificateChain> chain, const string& hostname)
{
if (chain->getCount() == 0)
return;
@@ -58,13 +59,14 @@ void defaultCertificateVerifier::verify(ref <certificateChain> chain)
const string type = chain->getAt(0)->getType();
if (type == "X.509")
- verifyX509(chain);
+ verifyX509(chain, hostname);
else
throw exceptions::unsupported_certificate_type(type);
}
-void defaultCertificateVerifier::verifyX509(ref <certificateChain> chain)
+void defaultCertificateVerifier::verifyX509
+ (ref <certificateChain> chain, const string& hostname)
{
// For every certificate in the chain, verify that the certificate
// has been issued by the next certificate in the chain
@@ -141,6 +143,13 @@ void defaultCertificateVerifier::verifyX509(ref <certificateChain> chain)
throw exceptions::certificate_verification_exception
("Cannot verify certificate against trusted certificates.");
}
+
+ // Ensure the first certificate's subject name matches server hostname
+ if (!firstCert->verifyHostName(hostname))
+ {
+ throw exceptions::certificate_verification_exception
+ ("Server identity cannot be verified.");
+ }
}
diff --git a/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp b/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp
index 633004ff..b3f939ec 100644
--- a/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp
+++ b/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp
@@ -181,6 +181,12 @@ bool X509Certificate_GnuTLS::verify(ref <const X509Certificate> caCert_) const
}
+bool X509Certificate_GnuTLS::verifyHostName(const string& hostname) const
+{
+ return gnutls_x509_crt_check_hostname(m_data->cert, hostname.c_str()) != 0;
+}
+
+
const datetime X509Certificate_GnuTLS::getActivationDate() const
{
const time_t t = gnutls_x509_crt_get_activation_time(m_data->cert);
diff --git a/src/security/cert/openssl/X509Certificate_OpenSSL.cpp b/src/security/cert/openssl/X509Certificate_OpenSSL.cpp
index e47a19a4..3f171a4f 100755
--- a/src/security/cert/openssl/X509Certificate_OpenSSL.cpp
+++ b/src/security/cert/openssl/X509Certificate_OpenSSL.cpp
@@ -41,6 +41,8 @@
#include "vmime/exception.hpp"
#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/conf.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/err.h>
@@ -330,6 +332,72 @@ bool X509Certificate_OpenSSL::verify(ref <const X509Certificate> caCert_) const
}
+bool X509Certificate_OpenSSL::verifyHostName(const string& hostname) const
+{
+ // First, check subject common name against hostname
+ char CNBuffer[1024];
+ CNBuffer[sizeof(CNBuffer - 1)] = '\0';
+
+ X509_NAME* xname = X509_get_subject_name(m_data->cert);
+
+ if (X509_NAME_get_text_by_NID(xname, NID_commonName, CNBuffer, sizeof(CNBuffer)) != -1)
+ {
+ if (strcasecmp(CNBuffer, hostname.c_str()) == 0)
+ return true;
+ }
+
+ // Now, look in subject alternative names
+ for (int i = 0, extCount = X509_get_ext_count(m_data->cert) ; i < extCount ; ++i)
+ {
+ X509_EXTENSION* ext = X509_get_ext(m_data->cert, i);
+ const char* extStr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
+
+ if (strcmp(extStr, "subjectAltName") == 0)
+ {
+ const X509V3_EXT_METHOD* method;
+
+ if ((method = X509V3_EXT_get(ext)) != NULL)
+ {
+ const unsigned char* extVal = ext->value->data;
+ void *extValStr;
+
+ if (method->it)
+ {
+ extValStr = ASN1_item_d2i
+ (NULL, &extVal, ext->value->length, ASN1_ITEM_ptr(method->it));
+ }
+ else
+ {
+ extValStr = method->d2i
+ (NULL, &extVal, ext->value->length);
+ }
+
+ if (extValStr && method->i2v)
+ {
+ STACK_OF(CONF_VALUE)* val = method->i2v(method, extValStr, NULL);
+
+ for (int j = 0 ; j < sk_CONF_VALUE_num(val) ; ++j)
+ {
+ CONF_VALUE* cnf = sk_CONF_VALUE_value(val, j);
+
+ if ((strcasecmp(cnf->name, "DNS") == 0 &&
+ strcasecmp(cnf->value, hostname.c_str()) == 0)
+ ||
+ (strncasecmp(cnf->name, "IP", 2) == 0 &&
+ strcasecmp(cnf->value, hostname.c_str()) == 0))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
const datetime X509Certificate_OpenSSL::convertX509Date(void* time) const
{
char* buffer;
diff --git a/src/security/sasl/SASLSocket.cpp b/src/security/sasl/SASLSocket.cpp
index c3498d22..a4b0ea56 100644
--- a/src/security/sasl/SASLSocket.cpp
+++ b/src/security/sasl/SASLSocket.cpp
@@ -81,6 +81,18 @@ SASLSocket::size_type SASLSocket::getBlockSize() const
}
+const string SASLSocket::getPeerName() const
+{
+ return m_wrapped->getPeerName();
+}
+
+
+const string SASLSocket::getPeerAddress() const
+{
+ return m_wrapped->getPeerAddress();
+}
+
+
void SASLSocket::receive(string& buffer)
{
const size_type n = receiveRaw(m_recvBuffer, sizeof(m_recvBuffer));