From 3390cf27165d49ad7739b447b50927e874ec2c1e Mon Sep 17 00:00:00 2001 From: Shreyas Kalyan Date: Mon, 27 Apr 2020 21:29:56 -0700 Subject: SERVER-47811 Search the intermediate certificates for the issuer of the peer certificate --- jstests/ocsp/lib/mock_ocsp.js | 35 +++++++++---- jstests/ocsp/lib/ocsp_helpers.js | 4 ++ jstests/ocsp/ocsp_basic_ca_responder.js | 88 ++++++++++++++++++--------------- jstests/ocsp/ocsp_stapling.js | 19 +++---- 4 files changed, 88 insertions(+), 58 deletions(-) (limited to 'jstests/ocsp') diff --git a/jstests/ocsp/lib/mock_ocsp.js b/jstests/ocsp/lib/mock_ocsp.js index 1d8691bd26e..2827ece5e4c 100644 --- a/jstests/ocsp/lib/mock_ocsp.js +++ b/jstests/ocsp/lib/mock_ocsp.js @@ -11,15 +11,35 @@ const FAULT_UNKNOWN = "unknown"; const OCSP_PROGRAM = "jstests/ocsp/lib/ocsp_mock.py"; +class ResponderCertSet { + /** + * Set of certificates for the OCSP responder.' + * @param {string} cafile + * @param {string} certfile + * @param {string} keyfile + */ + constructor(cafile, certfile, keyfile) { + this.cafile = cafile; + this.certfile = certfile; + this.keyfile = keyfile; + } +} + +const OCSP_DELEGATE_RESPONDER = + new ResponderCertSet(OCSP_CA_PEM, OCSP_RESPONDER_CERT, OCSP_RESPONDER_KEY); +const OCSP_CA_RESPONDER = new ResponderCertSet(OCSP_CA_PEM, OCSP_CA_CERT, OCSP_CA_KEY); +const OCSP_INTERMEDIATE_RESPONDER = new ResponderCertSet( + OCSP_INTERMEDIATE_CA_PEM, OCSP_INTERMEDIATE_CA_CERT, OCSP_INTERMEDIATE_CA_KEY); + class MockOCSPServer { /** * Create a new OCSP Server. * * @param {string} fault_type * @param {number} next_update_secs - * @param {boolean} responder_is_ca + * @param {object} responder_certificate_set */ - constructor(fault_type, next_update_secs, responder_is_ca = false) { + constructor(fault_type, next_update_secs, responder_certificate_set = OCSP_DELEGATE_RESPONDER) { this.python = "python3"; this.fault_type = fault_type; @@ -27,16 +47,11 @@ class MockOCSPServer { this.python = "python.exe"; } - if (responder_is_ca) { - this.ocsp_cert_file = OCSP_CA_CERT; - this.ocsp_cert_key = OCSP_CA_KEY; - } else { - this.ocsp_cert_file = OCSP_RESPONDER_CERT; - this.ocsp_cert_key = OCSP_RESPONDER_KEY; - } + this.ca_file = responder_certificate_set.cafile; + this.ocsp_cert_file = responder_certificate_set.certfile; + this.ocsp_cert_key = responder_certificate_set.keyfile; print("Using python interpreter: " + this.python); - this.ca_file = OCSP_CA_PEM; // The port must be hard coded to match the port of the // responder in the certificates. this.port = 8100; diff --git a/jstests/ocsp/lib/ocsp_helpers.js b/jstests/ocsp/lib/ocsp_helpers.js index 9855c9405ad..073a13e6564 100644 --- a/jstests/ocsp/lib/ocsp_helpers.js +++ b/jstests/ocsp/lib/ocsp_helpers.js @@ -13,6 +13,10 @@ const OCSP_SERVER_MUSTSTAPLE_CERT = "jstests/libs/ocsp/server_ocsp_mustStaple.pe const OCSP_SERVER_CERT_REVOKED = "jstests/libs/ocsp/server_ocsp_revoked.pem"; const OCSP_RESPONDER_CERT = "jstests/libs/ocsp/ocsp_responder.crt"; const OCSP_RESPONDER_KEY = "jstests/libs/ocsp/ocsp_responder.key"; +const OCSP_INTERMEDIATE_CA_PEM = "jstests/libs/ocsp/intermediate_ca_ocsp.pem"; +const OCSP_INTERMEDIATE_CA_CERT = "jstests/libs/ocsp/intermediate_ca_ocsp.crt"; +const OCSP_INTERMEDIATE_CA_KEY = "jstests/libs/ocsp/intermediate_ca_ocsp.key"; +const OCSP_SERVER_INTERMEDIATE_CA_CERT = "jstests/libs/ocsp/server_intermediate_ca_ocsp.pem"; var clearOCSPCache = function() { let provider = determineSSLProvider(); diff --git a/jstests/ocsp/ocsp_basic_ca_responder.js b/jstests/ocsp/ocsp_basic_ca_responder.js index 0a13d0acad7..f3a7ca3d9fe 100644 --- a/jstests/ocsp/ocsp_basic_ca_responder.js +++ b/jstests/ocsp/ocsp_basic_ca_responder.js @@ -9,44 +9,54 @@ load("jstests/ocsp/lib/mock_ocsp.js"); if (determineSSLProvider() === "apple") { return; } +function test(serverCert, caCert, responderCertPair) { + clearOCSPCache(); + + const ocsp_options = { + sslMode: "requireSSL", + sslPEMKeyFile: serverCert, + sslCAFile: caCert, + sslAllowInvalidHostnames: "", + setParameter: { + "failpoint.disableStapling": "{'mode':'alwaysOn'}", + "ocspEnabled": "true", + }, + }; + + // This is to test what happens when the responder is down, + // making sure that we soft fail. + let conn = null; + + let mock_ocsp = new MockOCSPServer("", 1, responderCertPair); + mock_ocsp.start(); + + assert.doesNotThrow(() => { + conn = MongoRunner.runMongod(ocsp_options); + }); + + mock_ocsp.stop(); + mock_ocsp = new MockOCSPServer(FAULT_REVOKED, 1, responderCertPair); + mock_ocsp.start(); + + assert.throws(() => { + new Mongo(conn.host); + }); + + MongoRunner.stopMongod(conn); + + // The mongoRunner spawns a new Mongo Object to validate the collections which races + // with the shutdown logic of the mock_ocsp responder on some platforms. We need this + // sleep to make sure that the threads don't interfere with each other. + sleep(1000); + mock_ocsp.stop(); +} + +test(OCSP_SERVER_CERT, OCSP_CA_PEM, OCSP_CA_RESPONDER); + +// TODO: SERVER-47963 - remove this platform check. +if (determineSSLProvider() === "windows") { + return; +} -clearOCSPCache(); - -const ocsp_options = { - sslMode: "requireSSL", - sslPEMKeyFile: OCSP_SERVER_CERT, - sslCAFile: OCSP_CA_PEM, - sslAllowInvalidHostnames: "", - setParameter: { - "failpoint.disableStapling": "{'mode':'alwaysOn'}", - "ocspEnabled": "true", - }, -}; - -// This is to test what happens when the responder is down, -// making sure that we soft fail. -let conn = null; - -let mock_ocsp = new MockOCSPServer("", 1, true); -mock_ocsp.start(); - -assert.doesNotThrow(() => { - conn = MongoRunner.runMongod(ocsp_options); -}); - -mock_ocsp.stop(); -mock_ocsp = new MockOCSPServer(FAULT_REVOKED, 1, true); -mock_ocsp.start(); - -assert.throws(() => { - new Mongo(conn.host); -}); - -MongoRunner.stopMongod(conn); - -// The mongoRunner spawns a new Mongo Object to validate the collections which races -// with the shutdown logic of the mock_ocsp responder on some platforms. We need this -// sleep to make sure that the threads don't interfere with each other. -sleep(1000); -mock_ocsp.stop(); +test(OCSP_SERVER_INTERMEDIATE_CA_CERT, OCSP_INTERMEDIATE_CA_PEM, OCSP_INTERMEDIATE_RESPONDER); }()); \ No newline at end of file diff --git a/jstests/ocsp/ocsp_stapling.js b/jstests/ocsp/ocsp_stapling.js index 02671770fb6..d3e72e72af3 100644 --- a/jstests/ocsp/ocsp_stapling.js +++ b/jstests/ocsp/ocsp_stapling.js @@ -14,11 +14,11 @@ if (!supportsStapling()) { return; } -var test = function(responderCA) { +function test(serverCert, caCert, responderCertPair) { const ocsp_options = { sslMode: "requireSSL", - sslPEMKeyFile: OCSP_SERVER_CERT, - sslCAFile: OCSP_CA_PEM, + sslPEMKeyFile: serverCert, + sslCAFile: caCert, sslAllowInvalidHostnames: "", setParameter: { "ocspEnabled": "true", @@ -35,7 +35,7 @@ var test = function(responderCA) { MongoRunner.stopMongod(conn); - let mock_ocsp = new MockOCSPServer("", 1000, responderCA); + let mock_ocsp = new MockOCSPServer("", 1000, responderCertPair); mock_ocsp.start(); // In this scenario, the Mongod has the ocsp response stapled @@ -48,7 +48,7 @@ var test = function(responderCA) { }); mock_ocsp.stop(); - mock_ocsp = new MockOCSPServer(FAULT_REVOKED, 1000, responderCA); + mock_ocsp = new MockOCSPServer(FAULT_REVOKED, 1000, responderCertPair); mock_ocsp.start(); assert.doesNotThrow(() => { new Mongo(conn.host); @@ -70,7 +70,7 @@ var test = function(responderCA) { }); mock_ocsp.stop(); - mock_ocsp = new MockOCSPServer("", 1000, responderCA); + mock_ocsp = new MockOCSPServer("", 1000, responderCertPair); mock_ocsp.start(); assert.throws(() => { @@ -84,8 +84,9 @@ var test = function(responderCA) { // sleep to make sure that the threads don't interfere with each other. sleep(1000); mock_ocsp.stop(); -}; +} -test(false); -test(true); +test(OCSP_SERVER_CERT, OCSP_CA_PEM, OCSP_DELEGATE_RESPONDER); +test(OCSP_SERVER_CERT, OCSP_CA_PEM, OCSP_CA_RESPONDER); +test(OCSP_SERVER_INTERMEDIATE_CA_CERT, OCSP_INTERMEDIATE_CA_PEM, OCSP_INTERMEDIATE_RESPONDER); }()); \ No newline at end of file -- cgit v1.2.1