summaryrefslogtreecommitdiff
path: root/cpp/src/IceSSL/Instance.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/IceSSL/Instance.cpp')
-rw-r--r--cpp/src/IceSSL/Instance.cpp154
1 files changed, 82 insertions, 72 deletions
diff --git a/cpp/src/IceSSL/Instance.cpp b/cpp/src/IceSSL/Instance.cpp
index 6983eda8c97..704fdb118ee 100644
--- a/cpp/src/IceSSL/Instance.cpp
+++ b/cpp/src/IceSSL/Instance.cpp
@@ -389,7 +389,7 @@ IceSSL::Instance::initialize()
{
ERR_clear_error();
err = SSL_CTX_load_verify_locations(_ctx, file, dir);
- if(err || !passwordError())
+ if(err)
{
break;
}
@@ -459,7 +459,7 @@ IceSSL::Instance::initialize()
{
ERR_clear_error();
err = SSL_CTX_use_certificate_chain_file(_ctx, file.c_str());
- if(err || !passwordError())
+ if(err)
{
break;
}
@@ -524,7 +524,7 @@ IceSSL::Instance::initialize()
{
ERR_clear_error();
err = SSL_CTX_use_PrivateKey_file(_ctx, file.c_str(), SSL_FILETYPE_PEM);
- if(err || !passwordError())
+ if(err)
{
break;
}
@@ -789,11 +789,15 @@ IceSSL::Instance::verifyPeer(SSL* ssl, SOCKET fd, const string& address, const s
}
//
- // Extract the IP addresses and the DNS names from the subject
- // alternative names.
+ // For an outgoing connection, we compare the proxy address (if any) against
+ // fields in the server's certificate (if any).
//
- if(cert)
+ if(cert && !address.empty())
{
+ //
+ // Extract the IP addresses and the DNS names from the subject
+ // alternative names.
+ //
vector<pair<int, string> > subjectAltNames = cert->getSubjectAlternativeNames();
vector<string> ipAddresses;
vector<string> dnsNames;
@@ -801,95 +805,101 @@ IceSSL::Instance::verifyPeer(SSL* ssl, SOCKET fd, const string& address, const s
{
if(p->first == 7)
{
- ipAddresses.push_back(p->second);
+ ipAddresses.push_back(IceUtilInternal::toLower(p->second));
}
else if(p->first == 2)
{
- dnsNames.push_back(p->second);
+ dnsNames.push_back(IceUtilInternal::toLower(p->second));
}
}
//
- // Compare the peer's address against the dnsName and ipAddress values.
- // This is only relevant for an outgoing connection.
+ // Compare the peer's address against the common name.
//
- if(!address.empty())
+ bool certNameOK = false;
+ string dn;
+ string addrLower = IceUtilInternal::toLower(address);
{
- bool certNameOK = false;
-
- for(vector<string>::const_iterator p = ipAddresses.begin(); p != ipAddresses.end() && !certNameOK; ++p)
+ DistinguishedName d = cert->getSubjectDN();
+ dn = IceUtilInternal::toLower(string(d));
+ string cn = "cn=" + addrLower;
+ string::size_type pos = dn.find(cn);
+ if(pos != string::npos)
{
- if(address == *p)
- {
- certNameOK = true;
- break;
- }
+ //
+ // Ensure we match the entire common name.
+ //
+ certNameOK = (pos + cn.size() == dn.size()) || (dn[pos + cn.size()] == ',');
}
+ }
- if(!certNameOK && !dnsNames.empty())
+ //
+ // Compare the peer's address against the the dnsName and ipAddress
+ // values in the subject alternative name.
+ //
+ if(!certNameOK)
+ {
+ certNameOK = find(ipAddresses.begin(), ipAddresses.end(), addrLower) != ipAddresses.end();
+ }
+ if(!certNameOK)
+ {
+ certNameOK = find(dnsNames.begin(), dnsNames.end(), addrLower) != dnsNames.end();
+ }
+
+ //
+ // Log a message if the name comparison fails. If CheckCertName is defined,
+ // we also raise an exception to abort the connection. Don't log a message if
+ // CheckCertName is not defined and a verifier is present.
+ //
+ if(!certNameOK && (_checkCertName || (_securityTraceLevel >= 1 && !_verifier)))
+ {
+ ostringstream ostr;
+ ostr << "IceSSL: ";
+ if(!_checkCertName)
{
- string host = IceUtilInternal::toLower(address);
- for(vector<string>::const_iterator p = dnsNames.begin(); p != dnsNames.end() && !certNameOK; ++p)
- {
- string s = IceUtilInternal::toLower(*p);
- if(host == s)
- {
- certNameOK = true;
- }
- }
+ ostr << "ignoring ";
}
-
- //
- // Log a message if the name comparison fails. If CheckCertName is defined,
- // we also raise an exception to abort the connection. Don't log a message if
- // CheckCertName is not defined and a verifier is present.
- //
- if(!certNameOK && (_checkCertName || (_securityTraceLevel >= 1 && !_verifier)))
+ ostr << "certificate validation failure:\npeer certificate does not have `" << address
+ << "' as its commonName or in its subjectAltName extension";
+ if(!dn.empty())
{
- ostringstream ostr;
- ostr << "IceSSL: ";
- if(!_checkCertName)
- {
- ostr << "ignoring ";
- }
- ostr << "certificate validation failure:\npeer certificate does not contain `"
- << address << "' in its subjectAltName extension";
- if(!dnsNames.empty())
+ ostr << "\nSubject DN: " << dn;
+ }
+ if(!dnsNames.empty())
+ {
+ ostr << "\nDNS names found in certificate: ";
+ for(vector<string>::const_iterator p = dnsNames.begin(); p != dnsNames.end(); ++p)
{
- ostr << "\nDNS names found in certificate: ";
- for(vector<string>::const_iterator p = dnsNames.begin(); p != dnsNames.end(); ++p)
+ if(p != dnsNames.begin())
{
- if(p != dnsNames.begin())
- {
- ostr << ", ";
- }
- ostr << *p;
+ ostr << ", ";
}
+ ostr << *p;
}
- if(!ipAddresses.empty())
+ }
+ if(!ipAddresses.empty())
+ {
+ ostr << "\nIP addresses found in certificate: ";
+ for(vector<string>::const_iterator p = ipAddresses.begin(); p != ipAddresses.end(); ++p)
{
- ostr << "\nIP addresses found in certificate: ";
- for(vector<string>::const_iterator p = ipAddresses.begin(); p != ipAddresses.end(); ++p)
+ if(p != ipAddresses.begin())
{
- if(p != ipAddresses.begin())
- {
- ostr << ", ";
- }
- ostr << *p;
+ ostr << ", ";
}
+ ostr << *p;
}
- string msg = ostr.str();
- if(_securityTraceLevel >= 1)
- {
- Trace out(_logger, _securityTraceCategory);
- out << msg;
- }
- if(_checkCertName)
- {
- SecurityException ex(__FILE__, __LINE__);
- ex.reason = msg;
- throw ex;
- }
+ }
+ string msg = ostr.str();
+ if(_securityTraceLevel >= 1)
+ {
+ Trace out(_logger, _securityTraceCategory);
+ out << msg;
+ }
+ if(_checkCertName)
+ {
+ SecurityException ex(__FILE__, __LINE__);
+ ex.reason = msg;
+ throw ex;
}
}
}