summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/ssl/mongo_uri_secondaries.js16
-rw-r--r--src/mongo/util/net/ssl_manager_windows.cpp60
2 files changed, 57 insertions, 19 deletions
diff --git a/jstests/ssl/mongo_uri_secondaries.js b/jstests/ssl/mongo_uri_secondaries.js
index 6970015cc12..a4ed1eae93c 100644
--- a/jstests/ssl/mongo_uri_secondaries.js
+++ b/jstests/ssl/mongo_uri_secondaries.js
@@ -61,16 +61,14 @@ const subShellCommandFormatter = function(replSet) {
return command;
};
-const subShellArgs = [
- "env",
- "SSL_CERT_FILE=jstests/libs/trusted-ca.pem",
- 'mongo',
- '--nodb',
- '--eval',
- subShellCommandFormatter(rst)
-];
+function runWithEnv(args, env) {
+ const pid = _startMongoProgram({args: args, env: env});
+ return waitProgram(pid);
+}
+
+const subShellArgs = ['mongo', '--nodb', '--eval', subShellCommandFormatter(rst)];
-const retVal = _runMongoProgram(...subShellArgs);
+const retVal = runWithEnv(subShellArgs, {"SSL_CERT_FILE": "jstests/libs/trusted-ca.pem"});
assert.eq(retVal, 0, 'mongo shell did not succeed with exit code 0');
rst.stopSet();
diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp
index ccae93b440f..ec50095fa05 100644
--- a/src/mongo/util/net/ssl_manager_windows.cpp
+++ b/src/mongo/util/net/ssl_manager_windows.cpp
@@ -40,6 +40,7 @@
#include <string>
#include <tuple>
#include <vector>
+#include <winhttp.h>
#include "mongo/base/init.h"
#include "mongo/base/initializer_context.h"
@@ -310,6 +311,7 @@ private:
CERT_CHAIN_ENGINE_CONFIG userConfig;
UniqueCertChainEngine user;
UniqueCertStore CAstore;
+ bool hasCRL;
};
Status _initChainEngines(CAEngine* engine);
@@ -1288,6 +1290,7 @@ Status SSLManagerWindows::_loadCertificates(const SSLParams& params) {
}
_clientEngine.CAstore = std::move(swChain.getValue());
+ _clientEngine.hasCRL = !params.sslCRLFile.empty();
}
const auto serverCAFile =
@@ -1299,6 +1302,7 @@ Status SSLManagerWindows::_loadCertificates(const SSLParams& params) {
}
_serverEngine.CAstore = std::move(swChain.getValue());
+ _serverEngine.hasCRL = !params.sslCRLFile.empty();
}
if (hasCertificateSelector(params.sslCertificateSelector)) {
@@ -1684,6 +1688,7 @@ Status validatePeerCertificate(const std::string& remoteHost,
HCERTCHAINENGINE certChainEngine,
bool allowInvalidCertificates,
bool allowInvalidHostnames,
+ bool hasCRL,
SSLX509Name* peerSubjectName) {
CERT_CHAIN_PARA certChainPara;
memset(&certChainPara, 0, sizeof(certChainPara));
@@ -1780,11 +1785,41 @@ Status validatePeerCertificate(const std::string& remoteHost,
// This means the certificate chain is not valid.
// Ignore CRYPT_E_NO_REVOCATION_CHECK since most CAs lack revocation information especially test
- // certificates
+ // certificates. Either there needs to be a CRL, a CrlDistributionPoint in the Cert or OCSP and
+ // user-generated certs lack this information.
if (certChainPolicyStatus.dwError != S_OK &&
certChainPolicyStatus.dwError != CRYPT_E_NO_REVOCATION_CHECK) {
- auto swAltNames = getSubjectAlternativeNames(cert);
- if (certChainPolicyStatus.dwError == CERT_E_CN_NO_MATCH || allowInvalidCertificates) {
+ bool onlyCNError = false;
+
+ // Try again to validate if the cert has any other errors besides a CN mismatch
+ if (certChainPolicyStatus.dwError == CERT_E_CN_NO_MATCH && !allowInvalidCertificates) {
+
+ // We know the CNs do not match, are there any other issues?
+ sslCertChainPolicy.fdwChecks = SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
+
+ ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
+ certChainHolder.get(),
+ &chain_policy_para,
+ &certChainPolicyStatus);
+
+ // This means something really went wrong, this should not happen.
+ if (!ret) {
+ DWORD gle = GetLastError();
+ return Status(ErrorCodes::InvalidSSLConfiguration,
+ str::stream() << "CertVerifyCertificateChainPolicy2 failed: "
+ << errnoWithDescription(gle));
+ }
+
+ if (certChainPolicyStatus.dwError == S_OK ||
+ certChainPolicyStatus.dwError == CRYPT_E_NO_REVOCATION_CHECK) {
+ onlyCNError = true;
+ }
+ }
+
+ // We need to check if the user has a cert where SANs have ip addresses label as DNS Name
+ // but only if a CN mismatch is the only error
+ if (onlyCNError || allowInvalidCertificates) {
+ auto swAltNames = getSubjectAlternativeNames(cert);
auto swCIDRRemoteHost = CIDR::parse(remoteHost);
if (swAltNames.isOK() && swCIDRRemoteHost.isOK()) {
auto remoteHostCIDR = swCIDRRemoteHost.getValue();
@@ -1821,7 +1856,6 @@ Status validatePeerCertificate(const std::string& remoteHost,
msg << "The server certificate does not match the host name. Hostname: " << remoteHost
<< " does not match " << certificateNames.str();
-
if (allowInvalidCertificates) {
LOGV2_WARNING(23274,
"SSL peer certificate validation failed ({errorCode}): {error}",
@@ -1829,12 +1863,14 @@ Status validatePeerCertificate(const std::string& remoteHost,
"errorCode"_attr = integerToHex(certChainPolicyStatus.dwError),
"error"_attr = errnoWithDescription(certChainPolicyStatus.dwError));
- LOGV2_WARNING(23275,
- "The server certificate does not match the host name. Hostname: "
- "{remoteHost} does not match {certificateNames}",
- "The server certificate does not match the host name",
- "remoteHost"_attr = remoteHost,
- "certificateNames"_attr = certificateNames.str());
+ if (certChainPolicyStatus.dwError == CERT_E_CN_NO_MATCH) {
+ LOGV2_WARNING(23275,
+ "The server certificate does not match the host name. Hostname: "
+ "{remoteHost} does not match {certificateNames}",
+ "The server certificate does not match the host name",
+ "remoteHost"_attr = remoteHost,
+ "certificateNames"_attr = certificateNames.str());
+ }
*peerSubjectName = SSLX509Name();
return Status::OK();
@@ -1864,7 +1900,9 @@ Status validatePeerCertificate(const std::string& remoteHost,
return Status(ErrorCodes::SSLHandshakeFailed, msg);
}
}
+
uassertStatusOK(peerSubjectName->normalizeStrings());
+
return Status::OK();
}
@@ -1955,6 +1993,7 @@ Future<SSLPeerInfo> SSLManagerWindows::parseAndValidatePeerCertificate(
engine->machine,
_allowInvalidCertificates,
_allowInvalidHostnames,
+ engine->hasCRL,
&peerSubjectName);
if (!validateCertMachine.isOK()) {
// Validate against the current user store since this is easier for unprivileged users to
@@ -1964,6 +2003,7 @@ Future<SSLPeerInfo> SSLManagerWindows::parseAndValidatePeerCertificate(
engine->user,
_allowInvalidCertificates,
_allowInvalidHostnames,
+ engine->hasCRL,
&peerSubjectName);
if (!validateCertUser.isOK()) {
// Return the local machine status