SERVER-14861: Ensure that SSL hostname matching strictly follows RFC 2818

This commit is contained in:
Amalia Hawkins 2014-09-16 15:39:02 -04:00
parent a4c1edab3d
commit 8954a165aa
1 changed files with 23 additions and 16 deletions

View File

@ -955,22 +955,19 @@ namespace mongo {
return peerSubjectName; return peerSubjectName;
} }
int cnBegin = peerSubjectName.find("CN=") + 3; // Try to match using the Subject Alternate Name, if it exists.
int cnEnd = peerSubjectName.find(",", cnBegin); // RFC-2818 requires the Subject Alternate Name to be used if present.
std::string commonName = peerSubjectName.substr(cnBegin, cnEnd-cnBegin); // Otherwise, the most specific Common Name field in the subject field
// must be used.
if (_hostNameMatch(remoteHost.c_str(), commonName.c_str())) { bool sanMatch = false;
return peerSubjectName; bool cnMatch = false;
}
// If Common Name (CN) didn't match, check Subject Alternate Name (SAN)
STACK_OF(GENERAL_NAME)* sanNames = static_cast<STACK_OF(GENERAL_NAME)*> STACK_OF(GENERAL_NAME)* sanNames = static_cast<STACK_OF(GENERAL_NAME)*>
(X509_get_ext_d2i(peerCert, NID_subject_alt_name, NULL, NULL)); (X509_get_ext_d2i(peerCert, NID_subject_alt_name, NULL, NULL));
bool sanMatch = false;
if (sanNames != NULL) { if (sanNames != NULL) {
int sanNamesList = sk_GENERAL_NAME_num(sanNames); int sanNamesList = sk_GENERAL_NAME_num(sanNames);
for (int i = 0; i < sanNamesList; i++) { for (int i = 0; i < sanNamesList; i++) {
const GENERAL_NAME* currentName = sk_GENERAL_NAME_value(sanNames, i); const GENERAL_NAME* currentName = sk_GENERAL_NAME_value(sanNames, i);
if (currentName && currentName->type == GEN_DNS) { if (currentName && currentName->type == GEN_DNS) {
@ -982,10 +979,20 @@ namespace mongo {
} }
} }
} }
}
sk_GENERAL_NAME_pop_free(sanNames, GENERAL_NAME_free); sk_GENERAL_NAME_pop_free(sanNames, GENERAL_NAME_free);
}
else {
// If Subject Alternate Name (SAN) didn't exist, check Common Name (CN).
int cnBegin = peerSubjectName.find("CN=") + 3;
int cnEnd = peerSubjectName.find(",", cnBegin);
std::string commonName = peerSubjectName.substr(cnBegin, cnEnd-cnBegin);
if (!sanMatch) { if (_hostNameMatch(remoteHost.c_str(), commonName.c_str())) {
cnMatch = true;
}
}
if (!sanMatch && !cnMatch) {
if (_allowInvalidCertificates || _allowInvalidHostnames) { if (_allowInvalidCertificates || _allowInvalidHostnames) {
warning() << "The server certificate does not match the host name " << warning() << "The server certificate does not match the host name " <<
remoteHost; remoteHost;