diff options
23 files changed, 1027 insertions, 216 deletions
diff --git a/README.third_party.md b/README.third_party.md index 975d606109d..da40a71f26d 100644 --- a/README.third_party.md +++ b/README.third_party.md @@ -36,6 +36,8 @@ a notice will be included in | [linenoise] | BSD-3-Clause | | Unknown + changes | | ✗ | | [MozJS] | MPL-2.0 | ESR 60.9 | ESR 60.3.0 | | ✗ | | [MurmurHash3] | Public Domain | | Unknown + changes | ✗ | ✗ | +| [ocspbuilder] | MIT | 0.10.2 | 0.10.2 | | | +| [ocspresponder] | Apache-2.0 | 0.5.0 | 0.5.0 | | | | [Pcre] | BSD-3-Clause | 8.43 | 8.42 | | ✗ | | [S2] | Apache-2.0 | | Unknown | ✗ | ✗ | | [SafeInt] | MIT | 3.21 | 3.0.20p | | | @@ -66,6 +68,8 @@ a notice will be included in [linenoise]: https://github.com/antirez/linenoise [MozJS]: https://www.mozilla.org/en-US/security/known-vulnerabilities/firefox-esr [MurmurHash3]: https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp +[ocspbuilder]: https://github.com/wbond/ocspbuilder +[ocspresponder]: https://github.com/threema-ch/ocspresponder [Pcre]: http://www.pcre.org/ [S2]: https://github.com/google/s2geometry [SafeInt]: https://github.com/dcleblanc/SafeInt diff --git a/buildscripts/resmokeconfig/suites/ocsp.yml b/buildscripts/resmokeconfig/suites/ocsp.yml new file mode 100644 index 00000000000..25313657c53 --- /dev/null +++ b/buildscripts/resmokeconfig/suites/ocsp.yml @@ -0,0 +1,15 @@ +test_kind: js_test + +selector: + roots: + - jstests/ocsp/*.js + +executor: + config: + shell_options: + nodb: '' + readMode: commands + ssl: '' + tlsCAFile: jstests/libs/ocsp/ca_ocsp.pem + tlsCertificateKeyFile: jstests/libs/ocsp/client_ocsp.pem + sslAllowInvalidHostnames: '' diff --git a/etc/evergreen.yml b/etc/evergreen.yml index 417c5ffdd0e..f91859df734 100644 --- a/etc/evergreen.yml +++ b/etc/evergreen.yml @@ -3906,6 +3906,7 @@ tasks: - "src/mongo/util/options_parser/test_config_files/**" - "library_dependency_graph.json" - "src/third_party/JSON-Schema-Test-Suite/tests/draft4/**" + - "src/third_party/mock_ocsp_responder/**" - "bypass_compile_expansions.yml" - "patch_files.txt" - "artifacts.json" @@ -8207,6 +8208,16 @@ tasks: resmoke_jobs_max: 1 - <<: *task_template + name: ocsp + tags: ["ocsp"] + commands: + - func: "do setup" + - func: "run tests" + vars: + resmoke_args: --suites=ocsp + resmoke_jobs_max: 1 + +- <<: *task_template name: jsonSchema commands: - func: "do setup" @@ -9263,6 +9274,7 @@ buildvariants: - name: .logical_session_cache - name: .multi_shard - name: multi_stmt_txn_jscore_passthrough_with_migration_gen + - name: .ocsp - name: .read_write_concern - name: .replica_sets !.encrypt - name: .retry @@ -10976,6 +10988,7 @@ buildvariants: - name: .multi_shard - name: multi_stmt_txn_jscore_passthrough_with_migration_gen - name: multiversion + - name: .ocsp - name: .query_fuzzer - name: .read_write_concern .large distros: diff --git a/jstests/libs/ocsp/ca.cnf b/jstests/libs/ocsp/ca.cnf deleted file mode 100644 index 6c986139087..00000000000 --- a/jstests/libs/ocsp/ca.cnf +++ /dev/null @@ -1,70 +0,0 @@ -[ ca ] -default_ca = CA_default # The default ca section - -[ CA_default ] -dir = . # top dir -database = $dir/ca_state/index.txt # index file. -new_certs_dir = $dir/ca_state/newcerts # new certs dir -RANDFILE = $dir/ca_state/.rand # random number file - -certificate = $dir/ca.pem # The CA cert -serial = $dir/ca_state/serial # serial no file -private_key = $dir/ca.pem # CA private key - -default_days = 3650 # how long to certify for -default_crl_days= 3650 # how long before next CRL -default_md = sha256 # md to use -copy_extensions = copy -unique_subject = no - -policy = policy_any # default policy - -[ policy_any ] -countryName = optional -stateOrProvinceName = optional -localityName = optional -organizationName = optional -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -[ req ] -default_bits = 2048 -default_keyfile = privkey.pem -distinguished_name = req_distinguished_name -attributes = req_attributes -x509_extensions = usr_cert - -string_mask = utf8only - -[ req_attributes ] - -[ req_distinguished_name ] -commonName = Common Name (e.g. server FQDN or YOUR name) -commonName_max = 64 - -organizationalUnitName = Organizational Unit Name (eg, section) -organizationalUnitName_default = Kernel - -0.organizationName = Organization Name (eg, company) -0.organizationName_default = MongoDB - -localityName = Locality Name (eg, city) -localityName_default = New York City - -stateOrProvinceName = State or Province Name (full name) -stateOrProvinceName_default = New York - -countryName = Country Name (2 letter code) -countryName_default = US -countryName_min = 2 -countryName_max = 2 - -[ usr_cert ] -basicConstraints = CA:TRUE -authorityInfoAccess = OCSP;URI:http://localhost:8080 -keyUsage = nonRepudiation, digitalSignature, keyEncipherment -extendedKeyUsage = OCSPSigning - -[ crl_ext ] -authorityKeyIdentifier=keyid:always diff --git a/jstests/libs/ocsp/ca.crt b/jstests/libs/ocsp/ca.crt deleted file mode 100644 index 4f867be9638..00000000000 --- a/jstests/libs/ocsp/ca.crt +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDkzCCAnugAwIBAgIJANyMXUrZ5xe8MA0GCSqGSIb3DQEBCwUAMG8xEjAQBgNV -BAMMCWxvY2FsaG9zdDEPMA0GA1UECwwGS2VybmVsMRAwDgYDVQQKDAdNb25nb0RC -MRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MREwDwYDVQQIDAhOZXcgWW9yazELMAkG -A1UEBhMCVVMwHhcNMTkwOTIzMTU1MTU3WhcNMzkwOTE4MTU1MTU3WjBvMRIwEAYD -VQQDDAlsb2NhbGhvc3QxDzANBgNVBAsMBktlcm5lbDEQMA4GA1UECgwHTW9uZ29E -QjEWMBQGA1UEBwwNTmV3IFlvcmsgQ2l0eTERMA8GA1UECAwITmV3IFlvcmsxCzAJ -BgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3IruGz+g -xvKymbCPPQx/op8r+C5AFonxSqnZgyqT9oUzVQOXUM1/pZ5MLa6eA8C5vyaG+S1F -2wChIgo2Zhzqb/f57uMXP+lH1PTytuv0nFrqvC3Di5WG9ooeBASoxk6ARVxgbDj4 -W6sqQzt6hxQW1GyC6M0ArZtVkKm4svDhsxd8SpVvpVh0BvSta6G6PhicG8Tz8Xop -/uWuvBOXOlf33Yffx2Y7MRe0+/4L9WLUcK9GS3IobUlLPfNXX/kJPoq3DvoxAwZj -6JOd7zSLFBAReGr8pwZkqMetLX2aXTMpbUFIdcefCgvgLrr1HDz7pTAsaG/wm3wf -A+lzwV8qIymZvQIDAQABozIwMDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIF4DAT -BgNVHSUEDDAKBggrBgEFBQcDCTANBgkqhkiG9w0BAQsFAAOCAQEAGVGozVWRo8MB -QuJomR8d4uysZPVnYAvputJbZ6BqMv1/bOpjNmuw9h4P9ZFy8Q236qKklXJfun4K -+ZM008qUu6TX3l2EqjyQ+11jynHFt7v7r7hOzMFNjhsXyakspetOEPcsFQL4XCKl -fXkKaEwve7AXyh0t3fPawozjD15XUOpFTGAMpjX1ttlOze0f0DaCctYCYNkkE3HD -R48QW2j5+dw9VnzPD8q0RKWoBcg+VQYJDvRQj0ZCrcqhBHgG2+fkZUNZVEm/4Eko -mrG/OZ5yuN0ut3urfFNT+r3IiUk7wmBVTWifdC3JCUGirVYIcMg5nCaaFha8CUXX -YQaQWl6E7Q== ------END CERTIFICATE----- diff --git a/jstests/libs/ocsp/ca.key b/jstests/libs/ocsp/ca.key deleted file mode 100644 index f77ad4d1ee8..00000000000 --- a/jstests/libs/ocsp/ca.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA3IruGz+gxvKymbCPPQx/op8r+C5AFonxSqnZgyqT9oUzVQOX -UM1/pZ5MLa6eA8C5vyaG+S1F2wChIgo2Zhzqb/f57uMXP+lH1PTytuv0nFrqvC3D -i5WG9ooeBASoxk6ARVxgbDj4W6sqQzt6hxQW1GyC6M0ArZtVkKm4svDhsxd8SpVv -pVh0BvSta6G6PhicG8Tz8Xop/uWuvBOXOlf33Yffx2Y7MRe0+/4L9WLUcK9GS3Io -bUlLPfNXX/kJPoq3DvoxAwZj6JOd7zSLFBAReGr8pwZkqMetLX2aXTMpbUFIdcef -CgvgLrr1HDz7pTAsaG/wm3wfA+lzwV8qIymZvQIDAQABAoIBAFBE7KbUQMNIYELZ -5Th2DRp2Tn2U79SEPmNLcJRx8cqe7nD5zqAlO1lfRSC3VmHNSo3NCwE0PiGYmA0Y -pHYD/jvkiH4u/y5OzMswoAp91Nj3qkn1ah+qu6WN3aDexULwHXWhSqL5FUPgB5DS -3CS/5hNIr1jmDGIjkEAH1eajD7Kro0j9hj4I1yqMVphb1BVORw2NzmLfqLR9k/ru -UrobKuUHCw3HTgsVFinE11yGvCyUlSgH8NsdM044V7lyZlrneoAg+mqgky+Lolur -LuPrS97SekllJEXFqXZPek4hAG55X1sM2xpaBUDu7iStZFQDlekdmDt/DODwHfCj -oHTZhS0CgYEA/XGFIYQwBoQBXlUgf1YJlvQ2IH7q7gPYFSXlA/sXL6eateIltwYZ -Q4k/dgmSDMD1UxA0KZ776EJfCLlJCcLZ4QD5ylxaahfLBe/wAMBtI+hgCoOeWrpo -glswa1ZUUkzMoR3N6THoM2JE9mQjr2r7wKlpFxclDu2ESEbdX8weOYsCgYEA3sRy -4/rlYVu31BOMgU9B8Qh3uEFJXDKfWgYeHYeMMts/v6WKZmnfqPUvoO28UQlNNlWk -kO1L/2cqKhPNcGf/o8yPm7oeddwAOId3g2R5PB9hiKEhxD8fgAl89+5PunzU4doo -Po/osaZ0nBTzJ51iQoE5YoPdZXQA1Xt/wA2iktcCgYAGVpt0viCRWSXLnSdl59nv -i4X7BBGOCEyUItF6awImb/OfjttQm3dwR/NtWUnsxbqc7C/RxqcYJOjJiBC6jMP0 -K5kTpYGhW5z5Ngnzitxv5HTabnY8YKMSd4Nbe9o6AK+xa9Rle5kKB/AflVuLHIrV -Q6dcK3kCyY/gWt1YcvtihwKBgQCfPq2mvZc15rvdle/uDDtmU5hJlhocF3AEibUD -hP8657KFjJAIMA0bmdJnZyskftK8UbKni4q1VAk3NRq6DQ4ZCMVsHDtkI1XhEy3j -NnLYANLXOeCKilk5TQ8RqUFDXbNMlIgKWRON0yEu5mb/3aj9Q6VDAGLHAIsMERG8 -t8KM1wKBgGtYe4kC1PqlX8Uz+fbJuCP/dWkXzUcM5qsqQlO7ZRrBFZ5l+zGUyL+V -5IloSihaf16PAGaHIPjpKx/6lAo7BoFh/L2Y5s9KS5H+p2AGNKrJEOodMJp8A1dg -dUsWmD4/K7jpHWQEZeBZltlZRg9SFvJGtTQBTKQJx2OXHchxZWDu ------END RSA PRIVATE KEY----- diff --git a/jstests/libs/ocsp/ca_ocsp.pem b/jstests/libs/ocsp/ca_ocsp.pem new file mode 100644 index 00000000000..fe336fa4a12 --- /dev/null +++ b/jstests/libs/ocsp/ca_ocsp.pem @@ -0,0 +1,49 @@ +-----BEGIN CERTIFICATE----- +MIIDdDCCAlwCBBqPSvUwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCVVMxETAP +BgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAwDgYDVQQK +DAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxFzAVBgNVBAMMDktlcm5lbCBUZXN0 +IENBMB4XDTE5MTAzMTE5MDEyOVoXDTM5MTEwMjE5MDEyOVowdDELMAkGA1UEBhMC +VVMxETAPBgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAw +DgYDVQQKDAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxFzAVBgNVBAMMDktlcm5l +bCBUZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/9y4fkM +Xd3Tr6MIRNkyMvuaV4u7qEIpMGP/bHr7bMQnXFaGMnGBBCTCkIOg5lt34WwGC+U9 +BgZYxZovHs1KpGy5d41CZERlEGw2s2QPoam3f3u1i7qvYzeVmduYf91/39rBuiEu +BYPgLwhLY1Kka8WqCKEJCPcBj5SPCSQKIptl2hYHlvqYuGiVvnxSIPF00X/k7M6j +UEGMbTIzHEyYoEMpmgXbLf9H8Boy26cqcY3QJ+Bvd8xTw0kd2mhBgVieeGKvWm5s +k8rCoy+RtvPeDROZZ4qT0NTPYIhJaPRfHG+itu/CY2HQSSltOf9SSLSHlTm1wLFP +ujiUfsjNFFKaUQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQBDAHBBHA/v/wgzOH6aXOB6UXxXI8/KvcgrgdNFPt9DcIdRQiPKxtTs +P1olzu7cs5IvU5bsxZMU+L5NOFAozRFq4OLn2S6L7Hdh2akLJuOVKu3aDFpr7klT +VFZfgNvnP86eGoiaaqFX0ltY7mS4OAAIwikGOFSpyB6lGhPFAScwgSNaNGf8PAwu +6k+qA6WTdRkl9XO4o7e177zIV1GqRoD7QRe4dTNSJmLW9ZErO+u/+dgNLvTe4Me0 +DQ7an21tQmQ7I1WvdtHK074Trhj+XkcxwrjOr/Ee0EIz4O/dvDWFr9+VsCRwqjeC +IoBtRLeP/9erx5so5CuezhnjMuHTCM0p +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCz/3Lh+Qxd3dOv +owhE2TIy+5pXi7uoQikwY/9sevtsxCdcVoYycYEEJMKQg6DmW3fhbAYL5T0GBljF +mi8ezUqkbLl3jUJkRGUQbDazZA+hqbd/e7WLuq9jN5WZ25h/3X/f2sG6IS4Fg+Av +CEtjUqRrxaoIoQkI9wGPlI8JJAoim2XaFgeW+pi4aJW+fFIg8XTRf+TszqNQQYxt +MjMcTJigQymaBdst/0fwGjLbpypxjdAn4G93zFPDSR3aaEGBWJ54Yq9abmyTysKj +L5G2894NE5lnipPQ1M9giElo9F8cb6K278JjYdBJKW05/1JItIeVObXAsU+6OJR+ +yM0UUppRAgMBAAECggEBAJyuyHocKL+s0RAagqAr0J7AlWGPqRKWRPRyl2z+wM21 +Ee43Ayn107Cfrx3M9sqO5JO9TKYeLjiIXc3koQ/W9Bqc6fU/aYOOZcsd55/Qgirf +aXP3Y9j18KYVRIxhsyXa0e0yp2A2cbErUoKeXcFftvB5Z8GLLCo5mYo6bygtzwS/ +eSY6HpQ/IJiA6ptbkxOdlahNcNgZNYBUKwltYY8ExOHDyMJNAgK8izDmHKxjAQc8 +rqTxrgHf4Msd2jMc8B1I93q264gyZ/xMYS6OzVA/5ptCoFtgBRFLUxjTWXjsccXQ +M1Nj9E7TYIwV6WJJ8ZuKj3QimJ025ZgT4yTtJnD2QAECgYEA7PU0bkjpL/zTP6jE +6xI8hxcXxT/aIk41FTsSoiOBOWXk1bX7z7zdpdZieIJWHacrKUK/uZ53lzEA7X6l +HmWiA+JBvJtASw/nodl78Lq1mrmI5gdgYIexopXocFXnRMCv3tSLssZXBzjJo3yQ +99azJyThLdT741QfePQb9bGOQYECgYEAwnZwfloIaZiTD4Xf+ePyhtBBdGjhWCW5 +s7KIxkyFECXUtpZcz0+t8Chb3yuwjfJ+17YP3DWsm1nRaMCbq0Pzrv8tl77LZ/3t +HpW4GVM0XB5npX3Q87OdJF9T1pQDCfphanptyoe4HIht6G7nWnTlAKoijXM7Wiqb +FebdLth/INECgYBZi3gazRbB+ari/aYcpzGUY1eqRKzsFd3dfgtWllA5HpZRZIoa +QOcJynA/1hEw94FKAF1vicDrs6sEFL3VNNb63L+2xHyRYRtJgGRj3krOg5qGQvda +wyyPolLKUMwqoR5U+MEp9+XfZshcLbCi19Gv0zH9HeVqTNnv3V/LgyOdAQKBgQCY +KjmohSbkCiG5GdbDIV1bpIYzYwZCBXMka+We1a2hjxi9rzb8earvq4UIQpWq3T/n +52zNsapY/ZVhVKX7A/cgzkiM3x0nSIlNT3Z5SqREGP6dfrAMolWqanWeCL/ABQ5J +VXen7T9iBFeMc4vROnsfZAIZkTu2OHSWVMpqp7oCoQKBgCbUUhSlH1sdDOfiAzSp +YM2IVsVPNQJnraHb6UY2tFkkBAWM3nfnO/8FSN03k7g1/V3jgp9K6r3rGnCqgvxS +ufYvTgaaAkwdmZhcWbi0g2ffjmPvJ4axWmJ65RSeD6vkUZtCdD/XsX6AeHFvIK4O +kaeIUDVZ+r/DVZoV+/beBzcs +-----END PRIVATE KEY----- diff --git a/jstests/libs/ocsp/client_ocsp.pem b/jstests/libs/ocsp/client_ocsp.pem new file mode 100644 index 00000000000..3ab77920eea --- /dev/null +++ b/jstests/libs/ocsp/client_ocsp.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIID9jCCAt4CBHU3PtcwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCVVMxETAP +BgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAwDgYDVQQK +DAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxFzAVBgNVBAMMDktlcm5lbCBUZXN0 +IENBMB4XDTE5MTAzMTE5MDEyOVoXDTM5MTEwMjE5MDEyOVowYjEQMA4GA1UECgwH +TW9uZ29EQjEPMA0GA1UECwwGS2VybmVsMRIwEAYDVQQDDAlsb2NhbGhvc3QxCzAJ +BgNVBAYTAlVTMQswCQYDVQQIDAJOWTEPMA0GA1UEBwwGT0NTUC0yMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5eA6yCW44Zt82dWcMZbGB5rs+o/ePTQj +ild2zCmzK3icQB+km8gPSzMMlwAzvDMOoqFw95xqi7y5QIp54N1K+3IwDeaTTp/B +bnd8u/5p7l2RevDJBa4xOQg1bivuLZd/heINH767beUx1AbjeMz+gvjO5L5XW9U5 +FaH7sRpTbqfb0CmaRwDXjuWbsThGJFWLCupzo6qvqTTviS1bWPzVXuUWSF/EgMFY +tSdlL901Unlz1oe70JxqL0/eRFw6sIdOWnMoz2Fzf2b4cbQT53U20GbJGEbOfSTE +xPoucNSvA8XJ09zYSG1PlAApAZAjO1dNoIAeBcfxKzxg3NAzL21W0QIDAQABo4Gm +MIGjMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMC +MB0GA1UdDgQWBBQsP/tgzwdRz/N6UkXc7ljFBTPCSTA5BggrBgEFBQcBAQQtMCsw +KQYIKwYBBQUHMAGGHWh0dHA6Ly9sb2NhbGhvc3Q6ODEwMC9zdGF0dXMvMBoGA1Ud +EQQTMBGCCWxvY2FsaG9zdIcEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAN9T1RR/4 +cii8Qw2elnvPRlsYgzILH2BjbWcqFvoxbY8XMeMtHBltyzw5AFypV5V6PToU/j0/ +UkjDb3KNT07uLVjaSiIQVLSm26jLlWVSFQ1tDD6pQtdhIp6brYqLuw51FVMsFmTN +jI79YFQ2OyR2CrKA4Yrt7wYMePgz7DgftI84BLwkb5nTspt639/oik076ChVd98R +biJ8isIW5Nj9SGyvHC2WSq+xwtQMuK8at1WsQ1WO3dq0qZugPtDKxprSyAHvdG77 +kGAdyg3F3ljtuOvuik+4sMX31Uv3sLHYsZqg4GaPVMW4qzd1t0vs6lkxDiOkZvbJ +wOPtN/Vc75oxlw== +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDl4DrIJbjhm3zZ +1ZwxlsYHmuz6j949NCOKV3bMKbMreJxAH6SbyA9LMwyXADO8Mw6ioXD3nGqLvLlA +inng3Ur7cjAN5pNOn8Fud3y7/mnuXZF68MkFrjE5CDVuK+4tl3+F4g0fvrtt5THU +BuN4zP6C+M7kvldb1TkVofuxGlNup9vQKZpHANeO5ZuxOEYkVYsK6nOjqq+pNO+J +LVtY/NVe5RZIX8SAwVi1J2Uv3TVSeXPWh7vQnGovT95EXDqwh05acyjPYXN/Zvhx +tBPndTbQZskYRs59JMTE+i5w1K8DxcnT3NhIbU+UACkBkCM7V02ggB4Fx/ErPGDc +0DMvbVbRAgMBAAECggEASO0M2OgWsgP45MZ+icDSTCFbItY3Y+VBjSbYOkbUX2sg +7rrbJsyeBXZJfTIEN6Ve9DsRMox9xJz3jEEiDzNFEWYVVqOagevumpPvj1hT1Nn8 +SCtRKqsrVHOFN9FZ+z6/pwKitTp2DZQTbbdNvMoTyAsU375+ylRnirRbu8ClTUn7 +UcQkfvjWLjSanq8VxpnfUd0+6PCTZOmaRCRI1ZSU9Ctco7F9ZB6OSoJjvQcny/lY +GV7wsb2CWQcH4fxBxMB31s7YG3WlbAP4nPKqydylir78lUg4wGgKcSh8XqMJPyA6 +Hu4zx+oi7EFrMlGmJKssjz9BkYouSAE0kSHWhn6iwQKBgQD62ISTLsiYC8b4jy31 +VO9VqwjVL7eO71HfKi4vRQeIgSDCWHxz13UUXAP/dir91Tn/QJ3DmFfWudVb9oTs +MvUR8WuhBh2mR4+hTCzVN5++nsYQACUM3WYn6TwxpHTmy5fdG4L1QWaI15XbHudS +ml7wBJ/B8PCeLPF1X0na3QYkGQKBgQDqmWhL8pZH30kIelcxR8aSN8ukm2585Tdu +OVyEeYw9LrvCp7HzflakTYGjXxxO0iHRK7OLlgEfy8zr0Gs8/lzNcSKh5ftacLj0 +2k368kgpCnps7DBojmLCbEX0JAmw3zlsCOlGhwvD3LuTsO3WB8FfdoVeZhXji8A+ +XXgQ7UlfeQKBgHAnmq8L/dgte9rqeYv1W8Ub4akf2pxn2F1FSL0Nyh54TaNXWN2a +ediOg6MWvIYdbf74bxFi7fMtx32ErU3GQtiw7oRibaNI36kom+sBIcViy/+fcPFd +lC1IFQfFFheS8+WCRX1Orn+ElJYSLS87ojMCfkOCbLLsOVFXN3hJ1lMRAoGBAIca +XbQPOnidoEOfoQMiYLroIwDi+lg28RsrMZqhHSBG/550UMj3YxIwCI57QaQq44rA +bh/e/TrAdX0AhCGWIv+1Pcqa1YwaCooIBoyUZvYrsKF1y9MK3Nk23XpiHqqbg0gy +QZV6RE5BmkzNwcpWoQhHCzt38vceDlJcJb8px+2RAoGAUezn+Bokp1fB0tR7uxSd +gipIwRX8LTcgBhq56C0GbF5ku8yWs8Dl7FWvFOZdK7BBFf7o2g1KWDjL5EVjCIvx +sy3hknhq3EE6NVz1LmoBNM4aVmawtTZMn9u+sODgzTXaoSfkZ3IOZX7oXEFPSTBO +dVtTs0BXBHm3LzMYWtMI3/4= +-----END PRIVATE KEY----- diff --git a/jstests/libs/ocsp/ocsp_cert.crt b/jstests/libs/ocsp/ocsp_cert.crt deleted file mode 100644 index dd469331881..00000000000 --- a/jstests/libs/ocsp/ocsp_cert.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDPjCCAiYCAQEwDQYJKoZIhvcNAQELBQAwbzESMBAGA1UEAwwJbG9jYWxob3N0 -MQ8wDQYDVQQLDAZLZXJuZWwxEDAOBgNVBAoMB01vbmdvREIxFjAUBgNVBAcMDU5l -dyBZb3JrIENpdHkxETAPBgNVBAgMCE5ldyBZb3JrMQswCQYDVQQGEwJVUzAeFw0x -OTA5MjMxNTU1MTVaFw0yOTA5MjAxNTU1MTVaMFsxCzAJBgNVBAYTAlVTMQswCQYD -VQQIDAJDQTEMMAoGA1UEBwwDTllDMQwwCgYDVQQKDANNREIxDzANBgNVBAsMBktl -cm5lbDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEApl5gyAVH6ENyByOvPuTZ65L4TftlqUkzO4WflZ/DzLNU5B05F7ki -HLQQ9u0RtZCrCEvebPwRSpEmuKO733y7g22kKdkd8Nih8eWvl5zcMesGFf4GIgQY -vRqMEXEhQRE3bsgs+8YhA/rZrxXR+/1TP5Ph14jWPlsd6AgRWOCQAmsPO1kSDw8t -4f8Vtc/kmoRpF7SlMaaVjxFp7uyamBkwooCIzh8xzy/hf7wo71YiQ3qD22DeFHSV -Hyly5kwvap16HtGzyL9b9PgoD39D2knczAMVHf+qMjUlfMzjwdiB1vTup59JeEli -KyT+Gk2cy3z5LK4qsHbsSDNYlibYAYOvSwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB -AQCTEVMZETg2oiZtWspO7My87jtJkh5LcLLTU+JkGQFjXUxkHfag/TzH54fdZEDi -NF6hk73atdR4vANi8TID683840FtqRVvvk6Wx6MAwJq7//+54LBCPOiIVE+C0Tic -WeezDNheNb6XTGkwO5wiQ0UJFPdxb5lmTQYUo+VTBco0zgph+FcbHn6Phc4ZpS1H -D09r2J8/Jzip1ugqqdY8lO8wuKyCnVJqNiVsMBhnnW0nog89UVX9zSRPgh/gA6SN -XUZrel6WnmMihUJWtCkdwUDxiRXgqUWHbyRf2iX7UWXNBVrFeZYWQwmEJkJ0OKkT -l+F8o3nUue/sg98MWI9Zjx2U ------END CERTIFICATE----- diff --git a/jstests/libs/ocsp/ocsp_cert.key b/jstests/libs/ocsp/ocsp_cert.key deleted file mode 100644 index 1a3f11e8a8c..00000000000 --- a/jstests/libs/ocsp/ocsp_cert.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmXmDIBUfoQ3IH -I68+5NnrkvhN+2WpSTM7hZ+Vn8PMs1TkHTkXuSIctBD27RG1kKsIS95s/BFKkSa4 -o7vffLuDbaQp2R3w2KHx5a+XnNwx6wYV/gYiBBi9GowRcSFBETduyCz7xiED+tmv -FdH7/VM/k+HXiNY+Wx3oCBFY4JACaw87WRIPDy3h/xW1z+SahGkXtKUxppWPEWnu -7JqYGTCigIjOHzHPL+F/vCjvViJDeoPbYN4UdJUfKXLmTC9qnXoe0bPIv1v0+CgP -f0PaSdzMAxUd/6oyNSV8zOPB2IHW9O6nn0l4SWIrJP4aTZzLfPksriqwduxIM1iW -JtgBg69LAgMBAAECggEARyhw3rybf/VxDSqvJwh9SOwotjoDxn9foWLK2hVmiuRd -N+Bj7giqVXqTEvpdK7p/3OGOdjDuOGWTGUA2+CUCkvlPUPLjgoM16R/jlcZqzBMJ -HFj1SJFV/3QeWst3fLwfaIvH6bxZnLkraF693LkCZVwcKbMGZ89TIE5rFQefsNhn -NL09s5szt+A1q3gNf3U0qTf/+raquI0UUGp/X+fuLvqBRcn7lFow6iNybC3PI2oT -B4kJ3sPpoJZHW1VP0lqFUR0WaTo+GyJA2+TGSh5zz+AcDB56H5L04Tjq+WXhiZd2 -0vzxl8jbFQ/gwhzq7yg/PoHFrN5pupb6Wokuvc530QKBgQDP85z3cukyDQiw+3u/ -8lCCWJFUnTXFbReB3XxsqludNJ9b71t66XZcg48btdJ8DxZUjPShgBSHDH3lhfyT -yAil1v/xdfL12RmDWS/CKp9tLUBQa6P9fOWNObrDgl8pEE9/I6qxrSigVvsGDHMU -ed7l0z2Dtti5QXivpVuQfDREGQKBgQDMzx+n7nQchGvj8Ng2TlSBEWGk2a3jjASx -ioWY/PieR53BSvngnNjzssXWXiAUxdQQ5dosRTJAK60rVKIaRdXPzLl6vPOVnS1N -xrUK88xkZvOJtMqwqYm/efOJ4i8wgV/UxnP9TBsKkA1ilnIpvUp4g9o09L2Cko3d -RDwtBIJbAwKBgQC3JRAOYvb8bLxF2wbPM2MymTxNsDOmUAEPD/lAXv1Ww/zB5FnG -M41Zx0gnmIfrWQJKruXYwsvRcPAEUG/124u6O1Oo3j9/xJeStd64+/7zEZJ+AX8p -hnFJYxmYjN6wdLv+9nOkDiQkqtZkKlzEIN1tvhCES2ouJnpa/6BX7Pu/KQKBgQCo -K6atqLH0vJMuvpN6vATNWi1YRFlxT4aHFdwvTAEFTn7tuZfGZGQMbw3dwLoM9If2 -PBZSZZsmb/aobr0QX6l6EHt4mfBVOJN7mp8L2DZLdvGgcDBCsWNnM0bTQENJS+IZ -f768DSLjIHetLSWeukyM+o9RDmkR7y7HsgDLYjl7awKBgF7gUQDp+WG70Faixt5Y -/pmOgKqXWfKSuf2v4VVMX82rZrNz8XYGJ31vZ2qztpqwHkQK2yT55I9ekkPDuqHH -eP78YJVGKWNmRAzKmFQXZ5iIzdK1UF4C8gAoCjSNmBcRllKm28SEoKATTg+Gp54Y -51BtTFfdDlOy4nHD1OUHUT2i ------END PRIVATE KEY----- diff --git a/jstests/libs/ocsp/ocsp_responder.crt b/jstests/libs/ocsp/ocsp_responder.crt new file mode 100644 index 00000000000..2d2d4c283ef --- /dev/null +++ b/jstests/libs/ocsp/ocsp_responder.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfjCCAmYCBDxNPHcwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCVVMxETAP +BgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAwDgYDVQQK +DAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxFzAVBgNVBAMMDktlcm5lbCBUZXN0 +IENBMB4XDTE5MTAzMTE5MDEyOVoXDTM5MTEwMjE5MDEyOVowYjEQMA4GA1UECgwH +TW9uZ29EQjEPMA0GA1UECwwGS2VybmVsMRIwEAYDVQQDDAlsb2NhbGhvc3QxCzAJ +BgNVBAYTAlVTMQswCQYDVQQIDAJOWTEPMA0GA1UEBwwGT0NTUC0zMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAytlQOVc3n/5gB3BipK8bo9QDyB/Q1rBA +1ObExPJ/bBoHdZlV2+IJfjRiEAghiNQjo3J7vhfOZv5LZN5TAl+Gy1U00bbtfaRi +tiwi8hCNs8O3KrnOdVBWtAQsSpXHhPvGxuS0SIiRNqfu9jIFE3OZPWnfhkRlB5Oh ++ShWju+SOVZIDsK/HzQrl4YHCRbxigeTttmw9Rn/Bkma1YnX1/p6RoUjOi9T9u4h +8CcJMJq4H6sacOazu0f3/iT+LsNYvZFT8i4KzFgzipShKAYkyyLfIRl5P7sipagX +/rzzJ3EAkKXpKmwYRAg2vpjLnVspXKNF4PySynjBmoHzHf0vTsqRNQIDAQABoy8w +LTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUEDDAKBggrBgEFBQcDCTAN +BgkqhkiG9w0BAQsFAAOCAQEAb7TpxM48jx8u726LnKRbc2EWNWkLr11ILcm0gq2b +a321dQ8AGo+XhAjL1x61VEgoG4teMDdNrii/ahRzs2Aflcn/lNWgeZJku6WShjS1 +LHl5qqxtugWYNymdWPOjxGd1f0ye2qShxARvmkjtTBR5xP9D0/VmZDDw3WwvzU9B ++MHxYWxjjFcfLQiGZfgOVO/rqXQJMaIyMgHwfPqnSczmOpFuAlxvuuuMpD2pw4Gm +HfxSwJWKUxXg+vsNVXuOHmgJv+BAQ9NLAvS1MiYNXUmLrbUc7sdDdti7irue3OUC +1QorLXgomL526IC92v+aR4ZIS9tC0LxYig29E3e+kpRLtg== +-----END CERTIFICATE----- diff --git a/jstests/libs/ocsp/ocsp_responder.key b/jstests/libs/ocsp/ocsp_responder.key new file mode 100644 index 00000000000..96408c69aed --- /dev/null +++ b/jstests/libs/ocsp/ocsp_responder.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDK2VA5Vzef/mAH +cGKkrxuj1APIH9DWsEDU5sTE8n9sGgd1mVXb4gl+NGIQCCGI1COjcnu+F85m/ktk +3lMCX4bLVTTRtu19pGK2LCLyEI2zw7cquc51UFa0BCxKlceE+8bG5LRIiJE2p+72 +MgUTc5k9ad+GRGUHk6H5KFaO75I5VkgOwr8fNCuXhgcJFvGKB5O22bD1Gf8GSZrV +idfX+npGhSM6L1P27iHwJwkwmrgfqxpw5rO7R/f+JP4uw1i9kVPyLgrMWDOKlKEo +BiTLIt8hGXk/uyKlqBf+vPMncQCQpekqbBhECDa+mMudWylco0Xg/JLKeMGagfMd +/S9OypE1AgMBAAECggEAD7ei5a6CWt1E546ntgbzZ1BIMrt0XQ4vF9ABsxjvEps5 +tLz60BzFi4fXiVJ39rgpQsLeH66MiaJuiRRI7kgkk6C4hP9di3yvQVpOIt9xe1pQ +2PiorKJa9XvVSrosSXuQvVx/M5eRWODOPTlG92jfmMiZTzgBdALWbA3aFx0tAVAw +qenguNR0FDVR0qwuzS3YVW3N9uxIBva2y7n46cN+HHxfnenZJ+LjIDglGoiongrS +gVvZSOf+jlh9AUZhzx2C1idzFII/LeI+7N61bZkK4q9k3x9+/1eU11CcEI0Fd953 +Y5N+yT+nz51FIsDYHlQsxFo0qdDlQzzwSAbo+39xyQKBgQD8RtayVQeJlCRlOeEW +3bONeU3Al6fs5WYFCQER0050i5kfdChB4Gm/8zeGXYvMNoMANOUPW8xkt4ygzWkN +O01a9xr25oFL1dFidacuE2BaNTxCF0tCd3tfIPlw8sv21cbYJKyMjeJEj50Rs9hJ +wWqvh/umXRjDS49FEnz/n7JVuwKBgQDN17mA6ClcTu5il1oT39F6VDnLoJWDmNX8 +UWK6vSpDo5s/Pz+ue/JvV52sbouv+/BRRuC9cNx/S3upanVDEJEblNJI1YoXMGfa +0loCGIe2cPEZyoxnWOVtmqP7I8B2Rp76VY8HlywLBhgFVGOSt4nmRugRoaAqdsO3 ++magSYpNzwKBgQCHTEag5dFhC75pO51ocgZ1/XShsbQx7OXGFYopUTZmcufwYo+k +pQKSG5LP0SPEpgej+LpQfl8kNPyK0R9iJUfbXWNsvzrgvQ/Kymaa43Ftb9edanjG +cOYNotWkqdKR0x0Nlr2jtASB2LPYZqe9Bqp88WUZWByLwN5ZoQzA25j9OQKBgQCk +OeuvdAqjsfmxQS3F03kujwo5cto2zvZSw5/wesHAi0RuVoj5LbyDprSOgPgDpQ7b +2Z+upN/W06NKzDvYENyk07xeDbiJvb3uMItNRsLoBP3m5NnWDm+lXY5c7O49ryRh +d2eQ18R02xzJC8YRpUtpJMM8ZeYCWxTVsPq2AVZNswKBgQDwRyayKvdl/ciL3z/J +cJ3iTBOhU1puC94ioVrb1K0v1iwtD6JCoaWywUwnQWWYp/m6CnOG7FGQHb3RVLg/ +T1YXvNuqFpz+OfO4wsaPQDq+Gt3vMSrj2WDtIyyua3ti6Z80cfXxugxmY5fQWg6O +orZaC+mlIkYHVFmJeE23qN7FZA== +-----END PRIVATE KEY----- diff --git a/jstests/libs/ocsp/server_ocsp.pem b/jstests/libs/ocsp/server_ocsp.pem new file mode 100644 index 00000000000..0d94228ab04 --- /dev/null +++ b/jstests/libs/ocsp/server_ocsp.pem @@ -0,0 +1,52 @@ +-----BEGIN CERTIFICATE----- +MIIEADCCAugCBG/khX0wDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCVVMxETAP +BgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAwDgYDVQQK +DAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxFzAVBgNVBAMMDktlcm5lbCBUZXN0 +IENBMB4XDTE5MTAzMTE5MDEyOVoXDTM5MTEwMjE5MDEyOVowYjEQMA4GA1UECgwH +TW9uZ29EQjEPMA0GA1UECwwGS2VybmVsMRIwEAYDVQQDDAlsb2NhbGhvc3QxCzAJ +BgNVBAYTAlVTMQswCQYDVQQIDAJOWTEPMA0GA1UEBwwGT0NTUC0xMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3KAkwbKU90m5++/fBgFZY1GyxjzAhNdf +tlf+6V4ci7S/cz5byt1h0fEqwHDsWCOeU4RAm3jXcAwAU0ofYBkWIUM3llIxNkBx +RGo4MT5NmQqmT0mQ9Eq2295KxG/jRDOFYahhEb0j2VjKl5bbDBFMJVs1VBvijk5i +GFCWz3ZLlsEPNMtUfKjL0hhirJc9WShk89hst7dq19Vwg2Q9h4/cJe+17jT+YuO+ +av2xEgIGokZJCKlBkUYJ7tI/Fklc1FsRWohIiiKBcDOT0nlC0Avw6oJRVP8VewA9 +/KXCdnP5HnKP7hDi60u3AVekXwtwBXfa1L9cHRlWQ9MPnCySQBJuwwIDAQABo4Gw +MIGtMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMB +BggrBgEFBQcDAjAdBgNVHQ4EFgQUh9JgouAbzLBeyTGHLOxqTlEUD9IwOQYIKwYB +BQUHAQEELTArMCkGCCsGAQUFBzABhh1odHRwOi8vbG9jYWxob3N0OjgxMDAvc3Rh +dHVzLzAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwDQYJKoZIhvcNAQELBQAD +ggEBAIIRYrXwMa2MXXB3IBnKZZq8bxuUJCUiSPJtMoegNlI5Yd7mZor7+SCMDJbU +RhhfDMQa21gq5c5SBtnZ9v8qFr6p0M02DrqwnOc8+NoATpxwzSw/LcbgkxKiDzpV +LdRWwZSG8t1fF3FLMYpMhwK+Cz6P//vP4Ll8pQpYphluUn/xNNKIVtc0d4E9/9In +TBuLUqCnQEqYyMzTCyYx9rheNDPdcSPy5PuDkkqPVxhQrHuK0GCRy9KhDwZ3IIBg +fhxz1Z9nnRL3t2QykboPZrdTwG9uPsHTHHF+sEkD0rjab9zM9pC+37AwnyWeql07 +8Dnw977Q8tO83YaFC4krIAi4Pr8= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDcoCTBspT3Sbn7 +798GAVljUbLGPMCE11+2V/7pXhyLtL9zPlvK3WHR8SrAcOxYI55ThECbeNdwDABT +Sh9gGRYhQzeWUjE2QHFEajgxPk2ZCqZPSZD0Srbb3krEb+NEM4VhqGERvSPZWMqX +ltsMEUwlWzVUG+KOTmIYUJbPdkuWwQ80y1R8qMvSGGKslz1ZKGTz2Gy3t2rX1XCD +ZD2Hj9wl77XuNP5i475q/bESAgaiRkkIqUGRRgnu0j8WSVzUWxFaiEiKIoFwM5PS +eULQC/DqglFU/xV7AD38pcJ2c/keco/uEOLrS7cBV6RfC3AFd9rUv1wdGVZD0w+c +LJJAEm7DAgMBAAECggEANuxbGilV8lXVSgXGFJ2jXhlJkxYuqyNevWscl4YJPzJI +8uyUN2VzY6tRBEVYYPzE/m+PEeU8ZLVoI1PxiZ/VJYSxQufFPoc+a1SyFng3IyFG +k7hxsI8lBIlLPanI/wKAcvZS6/KVCReUn7Y7Y76uoSIanYyvktOqkfkGAjGl0apZ +pWfm1hr75DkJcErO/mnM1cQD18QOKykXOVv1vXqGNje+uf39Kup7pO9Cl5pH0tBo +dnJQSyE8fsigBu9Dev05iwI9MFHzta7mJsNDN8pQdsElSafKsST4GnZfhrPjEH9t +rT/QdeUTlOro88FRY6UAAncinfIwnbrjwy9D70r7eQKBgQD47lhxYQ3FuwLsueTL +ebzTZ3bkSffUk8BJg3cXzyF1gjTyAgbgltJ+DrV+QKOvvG2+8GMIo8hbo+1zrtxV +2NUnNAlTHyvj/1X02fMZDyZaOuO+2CXbQ9Vmla6GL0zRFMVb2vt/atBUwGB+CsXn +n9q2vkQheTMI5xGMs0F4bUGOrQKBgQDi5AaVX8U7m/UATox7zTzKHxxTYW63VuBg +kC/xVjNwTy/KUB8A3UEtypeCN4T62jsXPQa9hqy2f6kz6dx9fkgRV9EBFU2zNcuA +GJcUEU4mZkkSI0RUS4opLWdFHF9hli63AYiAxTNSqCx0UbGsaJbKoCsX6iLMVfgr +3sgPkYbRLwKBgEIj6gHt/J/N6aAGYGEj7mTpN7C+aofj3hJqSMldspErUHAA09z2 +leUCeXybJiK6WRqDenzAL6sRqjSzgD2bCD+LVvLr9Fh27lrJUgsVeGY/AWYiviQ9 +KMVB/gYPKUTgVPPsAii/s6zhFIJI0H6TfaRSd33BWysBYitVMY8S0HldAoGASu6b +7gEvFjyvcWZ/pvNlPCuCI1duRUZ/2+RCsSWS32iHk/1Z/+MSf5kE6JCFboNcOJSD +AVzU9YC71NVLaHaoPnIOKJlsi98cUjXMz2fXs37caw0Sp/Q6sNa54G06YvRCgVYU +StLV3FqGM/Q3BYWVJ142XTOKQomx6GsvD1U0fSkCgYEA3txxBL3NytgRDPbbrvTE +zcBThd3k1y4qPPu2LHdIzrLfxRHmy8CF4+LwptJdZWlN9AuS6HzUi+GqVhL7GnE/ ++23/MUmOxJKCi0PNpJ7KndPk1HL1ag23QKsQnueQjb8uasSx08BXUksnhXduZreD +OmH5pyRTGx58Vhv+X+G/cvc= +-----END PRIVATE KEY----- diff --git a/jstests/ocsp/lib/mock_ocsp.js b/jstests/ocsp/lib/mock_ocsp.js index 3795cf2fee2..00de55e3c86 100644 --- a/jstests/ocsp/lib/mock_ocsp.js +++ b/jstests/ocsp/lib/mock_ocsp.js @@ -2,6 +2,7 @@ * Starts a mock OCSP Server to test * OCSP certificate revocation. */ +load("jstests/ocsp/lib/ocsp_helpers.js"); // These are a list of faults to match the list of faults // in ocsp_mock.py. @@ -25,9 +26,9 @@ class MockOCSPServer { } print("Using python interpreter: " + this.python); - this.ca_file = "jstests/libs/ocsp/ca.crt"; - this.ocsp_cert_file = "jstests/libs/ocsp/ocsp_cert.crt"; - this.ocsp_cert_key = "jstests/libs/ocsp/ocsp_cert.key"; + this.ca_file = OCSP_CA_CERT; + this.ocsp_cert_file = OCSP_RESPONDER_CERT; + this.ocsp_cert_key = OCSP_RESPONDER_KEY; // The port must be hard coded to match the port of the // responder in the certificates. this.port = 8100; @@ -45,15 +46,15 @@ class MockOCSPServer { "--ocsp_responder_key=" + this.ocsp_cert_key ]; - this.pid = _startMongoProgram({args: args}); - assert(checkProgram(this.pid).alive); - if (this.fault_type) { args.push("--fault=" + this.fault_type); } + this.pid = _startMongoProgram({args: args}); + assert(checkProgram(this.pid).alive); + assert.soon(function() { - return rawMongoProgramOutput().search("Mock OCSP Responder is running") !== -1; + return rawMongoProgramOutput().search("Listening on") !== -1; }); sleep(1000); diff --git a/jstests/ocsp/lib/ocsp_helpers.js b/jstests/ocsp/lib/ocsp_helpers.js new file mode 100644 index 00000000000..18066e441fb --- /dev/null +++ b/jstests/ocsp/lib/ocsp_helpers.js @@ -0,0 +1,11 @@ +/** + * Helper variables and methods for OCSP + */ + +load("jstests/ssl/libs/ssl_helpers.js"); + +const OCSP_CA_CERT = "jstests/libs/ocsp/ca_ocsp.pem"; +const OCSP_SERVER_CERT = "jstests/libs/ocsp/server_ocsp.pem"; +const OCSP_CLIENT_CERT = "jstests/libs/ocsp/client_ocsp.pem"; +const OCSP_RESPONDER_CERT = "jstests/libs/ocsp/ocsp_responder.crt"; +const OCSP_RESPONDER_KEY = "jstests/libs/ocsp/ocsp_responder.key"; diff --git a/jstests/ocsp/lib/ocsp_mock.py b/jstests/ocsp/lib/ocsp_mock.py index 8f7b625666d..3ad31193890 100644 --- a/jstests/ocsp/lib/ocsp_mock.py +++ b/jstests/ocsp/lib/ocsp_mock.py @@ -5,25 +5,12 @@ Python script to interface as a mock OCSP responder. import argparse import logging -from datetime import datetime -from ocspresponder import OCSPResponder, CertificateStatus +import sys +import os -fault = None +sys.path.append(os.path.join(os.getcwd() ,'src', 'third_party', 'mock_ocsp_responder')) -def validate(serial: int): - if fault == FAULT_REVOKED: - return (CertificateStatus.revoked, datetime.today()) - elif fault == FAULT_UNKNOWN: - return (CertificateStatus.unknown, None) - return (CertificateStatus.good, None) - -def get_cert(serial: int): - """ - Assume the certificates are stored in the ``certs`` directory with the - serial as base filename. - """ - with open('jstests/libs/ocsp/serial/server-%s.pem' % serial, 'r') as f: - return f.read().strip() +import mock_ocsp_responder def main(): """Main entry point""" @@ -39,22 +26,14 @@ def main(): parser.add_argument('--ocsp_responder_key', type=str, required=True, help="OCSP Responder Keyfile") - parser.add_argument('--fault', choices=[FAULT_REVOKED, FAULT_UNKNOWN], type=str, help="Specify a specific fault to test") + parser.add_argument('--fault', choices=[mock_ocsp_responder.FAULT_REVOKED, mock_ocsp_responder.FAULT_UNKNOWN], type=str, help="Specify a specific fault to test") args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.DEBUG) - global fault - if args.fault: - fault = args.fault - print('Initializing OCSP Responder') - app = OCSPResponder( - args.ca_file, args.ocsp_responder_cert, args.ocsp_responder_key, - validate_func=validate, - cert_retrieve_func=get_cert, - ) + app = mock_ocsp_responder.OCSPResponder(args.ca_file, args.ocsp_responder_cert, args.ocsp_responder_key, args.fault) if args.verbose: app.serve(args.port, debug=True) diff --git a/jstests/ocsp/ocsp_basic.js b/jstests/ocsp/ocsp_basic.js new file mode 100644 index 00000000000..eb7c4823d15 --- /dev/null +++ b/jstests/ocsp/ocsp_basic.js @@ -0,0 +1,39 @@ +// Check that OCSP verification works +// @tags: [requires_http_client] + +load("jstests/ocsp/lib/mock_ocsp.js"); + +(function() { +"use strict"; + +let mock_ocsp = new MockOCSPServer(); +mock_ocsp.start(); + +const ocsp_options = { + sslMode: "requireSSL", + sslPEMKeyFile: OCSP_SERVER_CERT, + sslCAFile: OCSP_CA_CERT, + setParameter: { + ocspEnabled: "true", + }, + sslAllowInvalidHostnames: "", +}; + +let conn = null; +assert.doesNotThrow(() => { + conn = MongoRunner.runMongod(ocsp_options); +}); + +mock_ocsp.stop(); + +// Test Scenario when Mock OCSP Server replies stating +// that the OCSP status of the client cert is revoked. +mock_ocsp = new MockOCSPServer(FAULT_REVOKED); +mock_ocsp.start(); +assert.throws(() => { + new Mongo(conn.host); +}); + +mock_ocsp.stop(); +MongoRunner.stopMongod(conn); +}());
\ No newline at end of file diff --git a/jstests/ssl/x509/certs.yml b/jstests/ssl/x509/certs.yml index af42b21c097..b889ee8ffea 100644 --- a/jstests/ssl/x509/certs.yml +++ b/jstests/ssl/x509/certs.yml @@ -324,6 +324,81 @@ certs: extensions: {basicConstraints: {CA: true}} ### +# OCSP Tree +### + +- name: 'ca_ocsp.pem' + description: >- + Primary Root Certificate Authority + Most Certificates are issued by this CA. + Subject: {CN: 'Kernel Test CA'} + Issuer: self + include_header: false + output_path: 'jstests/libs/ocsp/' + extensions: + basicConstraints: + critical: true + CA: true + +- name: 'server_ocsp.pem' + description: >- + OCSP certificate for the mongodb server. + Subject: + CN: 'localhost' + C: US + ST: NY + L: OCSP-1 + Issuer: 'ca_ocsp.pem' + include_header: false + output_path: 'jstests/libs/ocsp/' + extensions: + basicConstraints: {CA: false} + subjectAltName: + DNS: localhost + IP: 127.0.0.1 + authorityInfoAccess: 'OCSP;URI:http://localhost:8100/status/' + subjectKeyIdentifier: hash + keyUsage: [digitalSignature, keyEncipherment] + extendedKeyUsage: [serverAuth, clientAuth] + +- name: 'client_ocsp.pem' + description: >- + OCSP certificate for the mongodb client. + Subject: + CN: 'localhost' + C: US + ST: NY + L: OCSP-2 + Issuer: 'ca_ocsp.pem' + include_header: false + output_path: 'jstests/libs/ocsp/' + extensions: + basicConstraints: {CA: false} + subjectAltName: + DNS: localhost + IP: 127.0.0.1 + authorityInfoAccess: 'OCSP;URI:http://localhost:8100/status/' + subjectKeyIdentifier: hash + keyUsage: [digitalSignature, keyEncipherment] + extendedKeyUsage: [clientAuth] + +- name: 'ocsp_responder.crt' + description: Certificate and key for the OCSP responder + Subject: + CN: 'localhost' + C: US + ST: NY + L: OCSP-3 + Issuer: 'ca_ocsp.pem' + include_header: false + keyfile: 'ocsp_responder.key' + output_path: 'jstests/libs/ocsp/' + extensions: + basicConstraints: {CA: false} + keyUsage: [nonRepudiation, digitalSignature, keyEncipherment] + extendedKeyUsage: [OCSPSigning] + +### # Rollover tree ### diff --git a/jstests/ssl/x509/mkcert.py b/jstests/ssl/x509/mkcert.py index f46bd12dd63..61defb35539 100755 --- a/jstests/ssl/x509/mkcert.py +++ b/jstests/ssl/x509/mkcert.py @@ -155,7 +155,7 @@ def set_general_dict_extension(x509, exts, cert, name, typed_values): else: value.append(key + ':' + val) - exts.append(OpenSSL.crypto.X509Extension(b'basicConstraints', critical, ','.join(value).encode('utf-8'), subject=x509)) + exts.append(OpenSSL.crypto.X509Extension(bytes(name, 'utf-8'), critical, ','.join(value).encode('utf-8'), subject=x509)) def set_general_list_extension(x509, exts, cert, name, values): """Set value elements for a given extension.""" @@ -177,6 +177,13 @@ def set_general_list_extension(x509, exts, cert, name, values): exts.append(OpenSSL.crypto.X509Extension(name.encode('utf-8'), critical, ','.join(tags).encode('utf-8'), subject=x509)) +def set_ocsp_extension(x509, exts, cert): + """Set the OCSP extension""" + ocsp = cert.get('extensions', {}).get('authorityInfoAccess') + if not ocsp: + return + exts.append(OpenSSL.crypto.X509Extension(b'authorityInfoAccess', False, ocsp.encode('utf-8'), subject=x509)) + def set_san_extension(x509, exts, cert): """Set the Subject Alternate Name extension.""" san = cert.get('extensions', {}).get('subjectAltName') @@ -288,9 +295,10 @@ def set_extensions(x509, cert): 'keyAgreement', 'keyCertSign', 'cRLSign', 'encipherOnly', 'decipherOnly']) set_general_list_extension(x509, exts, cert, 'extendedKeyUsage', [ 'serverAuth', 'clientAuth', 'codeSigning', 'emailProtection', 'timeStamping', - 'msCodeInd', 'msCodeCom', 'msCTLSign', 'msSGC', 'msEFS', 'nsSGC']) + 'msCodeInd', 'msCodeCom', 'msCTLSign', 'msSGC', 'msEFS', 'nsSGC', 'OCSPSigning']) enable_subject_key_identifier_extension(x509, exts, cert) enable_authority_key_identifier_extension(x509, exts, cert) + set_ocsp_extension(x509, exts, cert) set_san_extension(x509, exts, cert) set_mongo_roles_extension(exts, cert) @@ -321,11 +329,14 @@ def sign_cert(x509, cert, key): x509.sign(signing_key, sig) def get_header_comment(cert): + if not cert.get('include_header', True): + return '' """Header comment for every generated file.""" comment = "# Autogenerated file, do not edit.\n" comment = comment + '# Generate using jstests/ssl/x509/mkcert.py --config ' + CONFIGFILE comment = comment + ' ' + cert['name'] + "\n#\n" comment = comment + "# " + cert.get('description', '').replace("\n", "\n# ") + comment = comment + "\n" return comment def convert_cert_to_pkcs1(cert): @@ -380,10 +391,25 @@ def create_cert(cert): passphrase = passphrase.encode('utf-8') cipher = 'aes256' - open(make_filename(cert), 'wt').write( - get_header_comment(cert) + "\n" + - OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, x509).decode('ascii') + - OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key, cipher=cipher, passphrase=passphrase).decode('ascii')) + header = get_header_comment(cert) + # The OCSP responder certificate needs to have the key and the pem file separated. + if cert.get('keyfile', False): + keyfile = cert['keyfile'] + key_path_dict = {'output_path': cert['output_path'], 'name': keyfile} + open(make_filename(cert), 'wt').write( + header + + OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, x509).decode('ascii')) + + open(make_filename(key_path_dict), 'wt').write( + header + + OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key, cipher=cipher, passphrase=passphrase).decode('ascii')) + + else: + # OCSP certificates cannot have comments because the Mock OCSP responder cannot process comments in Certificates + open(make_filename(cert), 'wt').write( + header + + OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, x509).decode('ascii') + + OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key, cipher=cipher, passphrase=passphrase).decode('ascii')) if cert.get('pkcs1'): convert_cert_to_pkcs1(cert) @@ -513,8 +539,9 @@ def process_cert(cert): x509 = load_authority_file(append_cert)[0] if not x509: raise ValueError("Unable to find certificate '" + append_cert + "' to append") + header = "# Certificate from " + append_cert + "\n" if cert.get('include_header', True) else "" open(make_filename(cert), 'at').write( - "# Certificate from " + append_cert + "\n" + + header + OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, x509).decode('ascii')) def parse_command_line(): @@ -537,7 +564,7 @@ def validate_config(): if not CONFIG.get('certs'): raise ValueError('No certificates defined') - permissible = ['name', 'description', 'Subject', 'Issuer', 'append_cert', 'extensions', 'passphrase', 'output_path', 'hash', 'key_type', 'explicit_subject', 'serial', 'not_before', 'not_after', 'pkcs1', 'pkcs12'] + permissible = ['name', 'description', 'Subject', 'Issuer', 'append_cert', 'extensions', 'passphrase', 'output_path', 'hash', 'include_header', 'key_type', 'keyfile', 'explicit_subject', 'serial', 'not_before', 'not_after', 'pkcs1', 'pkcs12'] for cert in CONFIG.get('certs', []): keys = cert.keys() if not 'name' in keys: diff --git a/src/mongo/util/net/ocsp/ocsp_manager.cpp b/src/mongo/util/net/ocsp/ocsp_manager.cpp index 62d88c4858f..1b3bf98115e 100644 --- a/src/mongo/util/net/ocsp/ocsp_manager.cpp +++ b/src/mongo/util/net/ocsp/ocsp_manager.cpp @@ -34,7 +34,7 @@ namespace mongo { -StatusWith<std::vector<uint8_t>> ocspRequestStatus(ConstDataRange data, HostAndPort hostAndPort) { +StatusWith<std::vector<uint8_t>> ocspRequestStatus(ConstDataRange data, StringData responderURI) { auto client = HttpClient::create(); if (!client) { return Status(ErrorCodes::InternalErrorNotSupported, "HTTP Client not supported"); @@ -42,7 +42,7 @@ StatusWith<std::vector<uint8_t>> ocspRequestStatus(ConstDataRange data, HostAndP client->allowInsecureHTTP(true); client->setTimeout(kOCSPRequestTimeoutSeconds); client->setHeaders({"Content-Type: application/ocsp-request"}); - auto dataBuilder = client->post("http://" + hostAndPort.toString(), data); + auto dataBuilder = client->post("http://" + responderURI, data); if (dataBuilder.size() == 0) { return Status(ErrorCodes::SSLHandshakeFailed, "OCSP Validation Failed"); } diff --git a/src/mongo/util/net/ocsp/ocsp_manager.h b/src/mongo/util/net/ocsp/ocsp_manager.h index 82b96843d4a..5d2a3d1a9a5 100644 --- a/src/mongo/util/net/ocsp/ocsp_manager.h +++ b/src/mongo/util/net/ocsp/ocsp_manager.h @@ -41,6 +41,6 @@ constexpr Seconds kOCSPRequestTimeoutSeconds(5); * Constructs the HTTP client and sends the OCSP request to the responder. * Returns a vector of bytes to be constructed into a OCSP response. */ -StatusWith<std::vector<uint8_t>> ocspRequestStatus(ConstDataRange data, HostAndPort hostAndPort); +StatusWith<std::vector<uint8_t>> ocspRequestStatus(ConstDataRange data, StringData responderURI); } // namespace mongo
\ No newline at end of file diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp index 83bfb5a53db..3009d914996 100644 --- a/src/mongo/util/net/ssl_manager_openssl.cpp +++ b/src/mongo/util/net/ssl_manager_openssl.cpp @@ -1495,7 +1495,7 @@ struct OCSPRequestAndIDs { */ Status addOCSPUrlToMap(SSL* conn, X509* cert, - std::map<HostAndPort, OCSPRequestAndIDs>& ocspRequestMap, + std::map<std::string, OCSPRequestAndIDs>& ocspRequestMap, OCSPCertIDSet& uniqueCertIds) { UniqueOpenSSLStringStack aiaOCSP(X509_get1_ocsp(cert)); @@ -1549,7 +1549,8 @@ Status addOCSPUrlToMap(SSL* conn, OCSPRequestAndIDs reqAndIDs{UniqueOCSPRequest(OCSP_REQUEST_new()), OCSPCertIDSet()}; - auto [mapIter, _] = ocspRequestMap.try_emplace(hostAndPort, std::move(reqAndIDs)); + auto [mapIter, _] = ocspRequestMap.try_emplace( + str::stream() << host << ":" << port << path, std::move(reqAndIDs)); OCSP_request_add0_id(mapIter->second.request.get(), certID.release()); mapIter->second.certIDs.insert(std::move(certIDForArray)); @@ -1565,7 +1566,7 @@ Status addOCSPUrlToMap(SSL* conn, } struct OCSPContext { - std::map<HostAndPort, OCSPRequestAndIDs> ocspRequestMap; + std::map<std::string, OCSPRequestAndIDs> ocspRequestMap; OCSPCertIDSet uniqueCertIds; }; @@ -1579,7 +1580,7 @@ StatusWith<OCSPContext> extractOcspUris(SSL* conn, X509* peerCert, STACK_OF(X509) * intermediateCerts) { - std::map<HostAndPort, OCSPRequestAndIDs> ocspRequestMap; + std::map<std::string, OCSPRequestAndIDs> ocspRequestMap; OCSPCertIDSet uniqueCertIds; auto status = addOCSPUrlToMap(conn, peerCert, ocspRequestMap, uniqueCertIds); diff --git a/src/third_party/mock_ocsp_responder/mock_ocsp_responder.py b/src/third_party/mock_ocsp_responder/mock_ocsp_responder.py new file mode 100644 index 00000000000..64925b41e7b --- /dev/null +++ b/src/third_party/mock_ocsp_responder/mock_ocsp_responder.py @@ -0,0 +1,611 @@ +# +# This file has been modified in 2019 by MongoDB Inc. +# + +# OCSPBuilder is derived from https://github.com/wbond/ocspbuilder +# OCSPResponder is derived from https://github.com/threema-ch/ocspresponder + +# Copyright (c) 2015-2018 Will Bond <will@wbond.net> + +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Copyright 2016 Threema GmbH + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import unicode_literals, division, absolute_import, print_function + +import logging +import base64 +import inspect +import re +import enum +import sys +import textwrap +from datetime import datetime, timezone, timedelta +from typing import Callable, Tuple, Optional + +from asn1crypto import x509, keys, core, ocsp +from asn1crypto.ocsp import OCSPRequest, OCSPResponse +from oscrypto import asymmetric +from bottle import Bottle, HTTPResponse, request + +__version__ = '0.10.2' +__version_info__ = (0, 10, 2) + +logger = logging.getLogger(__name__) + +if sys.version_info < (3,): + byte_cls = str +else: + byte_cls = bytes + +def _pretty_message(string, *params): + """ + Takes a multi-line string and does the following: + - dedents + - converts newlines with text before and after into a single line + - strips leading and trailing whitespace + :param string: + The string to format + :param *params: + Params to interpolate into the string + :return: + The formatted string + """ + + output = textwrap.dedent(string) + + # Unwrap lines, taking into account bulleted lists, ordered lists and + # underlines consisting of = signs + if output.find('\n') != -1: + output = re.sub('(?<=\\S)\n(?=[^ \n\t\\d\\*\\-=])', ' ', output) + + if params: + output = output % params + + output = output.strip() + + return output + + +def _type_name(value): + """ + :param value: + A value to get the object name of + :return: + A unicode string of the object name + """ + + if inspect.isclass(value): + cls = value + else: + cls = value.__class__ + if cls.__module__ in set(['builtins', '__builtin__']): + return cls.__name__ + return '%s.%s' % (cls.__module__, cls.__name__) + +def _writer(func): + """ + Decorator for a custom writer, but a default reader + """ + + name = func.__name__ + return property(fget=lambda self: getattr(self, '_%s' % name), fset=func) + + +class OCSPResponseBuilder(object): + + _response_status = None + _certificate = None + _certificate_status = None + _revocation_date = None + _certificate_issuer = None + _hash_algo = None + _key_hash_algo = None + _nonce = None + _this_update = None + _next_update = None + _response_data_extensions = None + _single_response_extensions = None + + def __init__(self, response_status, certificate_status_list=[], revocation_date=None): + """ + Unless changed, responses will use SHA-256 for the signature, + and will be valid from the moment created for one week. + :param response_status: + A unicode string of OCSP response type: + - "successful" - when the response includes information about the certificate + - "malformed_request" - when the request could not be understood + - "internal_error" - when an internal error occured with the OCSP responder + - "try_later" - when the OCSP responder is temporarily unavailable + - "sign_required" - when the OCSP request must be signed + - "unauthorized" - when the responder is not the correct responder for the certificate + :param certificate_list: + A list of tuples with certificate serial number and certificate status objects. + certificate_status: + A unicode string of the status of the certificate. Only required if + the response_status is "successful". + - "good" - when the certificate is in good standing + - "revoked" - when the certificate is revoked without a reason code + - "key_compromise" - when a private key is compromised + - "ca_compromise" - when the CA issuing the certificate is compromised + - "affiliation_changed" - when the certificate subject name changed + - "superseded" - when the certificate was replaced with a new one + - "cessation_of_operation" - when the certificate is no longer needed + - "certificate_hold" - when the certificate is temporarily invalid + - "remove_from_crl" - only delta CRLs - when temporary hold is removed + - "privilege_withdrawn" - one of the usages for a certificate was removed + - "unknown" - the responder doesn't know about the certificate being requested + :param revocation_date: + A datetime.datetime object of when the certificate was revoked, if + the response_status is "successful" and the certificate status is + not "good" or "unknown". + """ + self._response_status = response_status + self._certificate_status_list = certificate_status_list + self._revocation_date = revocation_date + + self._key_hash_algo = 'sha1' + self._hash_algo = 'sha256' + self._response_data_extensions = {} + self._single_response_extensions = {} + + @_writer + def nonce(self, value): + """ + The nonce that was provided during the request. + """ + + if not isinstance(value, byte_cls): + raise TypeError(_pretty_message( + ''' + nonce must be a byte string, not %s + ''', + _type_name(value) + )) + + self._nonce = value + + @_writer + def certificate_issuer(self, value): + """ + An asn1crypto.x509.Certificate object of the issuer of the certificate. + This should only be set if the OCSP responder is not the issuer of + the certificate, but instead a special certificate only for OCSP + responses. + """ + + if value is not None: + is_oscrypto = isinstance(value, asymmetric.Certificate) + if not is_oscrypto and not isinstance(value, x509.Certificate): + raise TypeError(_pretty_message( + ''' + certificate_issuer must be an instance of + asn1crypto.x509.Certificate or + oscrypto.asymmetric.Certificate, not %s + ''', + _type_name(value) + )) + + if is_oscrypto: + value = value.asn1 + + self._certificate_issuer = value + + @_writer + def next_update(self, value): + """ + A datetime.datetime object of when the response may next change. This + should only be set if responses are cached. If responses are generated + fresh on every request, this should not be set. + """ + + if not isinstance(value, datetime): + raise TypeError(_pretty_message( + ''' + next_update must be an instance of datetime.datetime, not %s + ''', + _type_name(value) + )) + + self._next_update = value + + def build(self, responder_private_key=None, responder_certificate=None): + """ + Validates the request information, constructs the ASN.1 structure and + signs it. + The responder_private_key and responder_certificate parameters are onlystr + required if the response_status is "successful". + :param responder_private_key: + An asn1crypto.keys.PrivateKeyInfo or oscrypto.asymmetric.PrivateKey + object for the private key to sign the response with + :param responder_certificate: + An asn1crypto.x509.Certificate or oscrypto.asymmetric.Certificate + object of the certificate associated with the private key + :return: + An asn1crypto.ocsp.OCSPResponse object of the response + """ + if self._response_status != 'successful': + return ocsp.OCSPResponse({ + 'response_status': self._response_status + }) + + is_oscrypto = isinstance(responder_private_key, asymmetric.PrivateKey) + if not isinstance(responder_private_key, keys.PrivateKeyInfo) and not is_oscrypto: + raise TypeError(_pretty_message( + ''' + responder_private_key must be an instance ofthe c + asn1crypto.keys.PrivateKeyInfo or + oscrypto.asymmetric.PrivateKey, not %s + ''', + _type_name(responder_private_key) + )) + + cert_is_oscrypto = isinstance(responder_certificate, asymmetric.Certificate) + if not isinstance(responder_certificate, x509.Certificate) and not cert_is_oscrypto: + raise TypeError(_pretty_message( + ''' + responder_certificate must be an instance of + asn1crypto.x509.Certificate or + oscrypto.asymmetric.Certificate, not %s + ''', + _type_name(responder_certificate) + )) + + if cert_is_oscrypto: + responder_certificate = responder_certificate.asn1 + + if self._certificate_status_list is None: + raise ValueError(_pretty_message( + ''' + certificate_status_list must be set if the response_status is + "successful" + ''' + )) + + def _make_extension(name, value): + return { + 'extn_id': name, + 'critical': False, + 'extn_value': value + } + + responses = [] + for serial, status in self._certificate_status_list: + response_data_extensions = [] + single_response_extensions = [] + for name, value in self._response_data_extensions.items(): + response_data_extensions.append(_make_extension(name, value)) + if self._nonce: + response_data_extensions.append( + _make_extension('nonce', self._nonce) + ) + + if not response_data_extensions: + response_data_extensions = None + + for name, value in self._single_response_extensions.items(): + single_response_extensions.append(_make_extension(name, value)) + + if self._certificate_issuer: + single_response_extensions.append( + _make_extension( + 'certificate_issuer', + [ + x509.GeneralName( + name='directory_name', + value=self._certificate_issuer.subject + ) + ] + ) + ) + + if not single_response_extensions: + single_response_extensions = None + + responder_key_hash = getattr(responder_certificate.public_key, self._key_hash_algo) + + if status == 'good': + cert_status = ocsp.CertStatus( + name='good', + value=core.Null() + ) + elif status == 'unknown': + cert_status = ocsp.CertStatus( + name='unknown', + value=core.Null() + ) + else: + reason = status if status != 'revoked' else 'unspecified' + cert_status = ocsp.CertStatus( + name='revoked', + value={ + 'revocation_time': self._revocation_date, + 'revocation_reason': reason, + } + ) + + issuer = self._certificate_issuer if self._certificate_issuer else responder_certificate + + produced_at = datetime.now(timezone.utc) + + if self._this_update is None: + self._this_update = produced_at + + if self._next_update is None: + self._next_update = self._this_update + timedelta(days=7) + + response = { + 'cert_id': { + 'hash_algorithm': { + 'algorithm': self._key_hash_algo + }, + 'issuer_name_hash': getattr(issuer.subject, self._key_hash_algo), + 'issuer_key_hash': getattr(issuer.public_key, self._key_hash_algo), + 'serial_number': serial, + }, + 'cert_status': cert_status, + 'this_update': self._this_update, + 'next_update': self._next_update, + 'single_extensions': single_response_extensions + } + responses.append(response) + + response_data = ocsp.ResponseData({ + 'responder_id': ocsp.ResponderId(name='by_key', value=responder_key_hash), + 'produced_at': produced_at, + 'responses': responses, + 'response_extensions': response_data_extensions + }) + + signature_algo = responder_private_key.algorithm + if signature_algo == 'ec': + signature_algo = 'ecdsa' + + signature_algorithm_id = '%s_%s' % (self._hash_algo, signature_algo) + + if responder_private_key.algorithm == 'rsa': + sign_func = asymmetric.rsa_pkcs1v15_sign + elif responder_private_key.algorithm == 'dsa': + sign_func = asymmetric.dsa_sign + elif responder_private_key.algorithm == 'ec': + sign_func = asymmetric.ecdsa_sign + + if not is_oscrypto: + responder_private_key = asymmetric.load_private_key(responder_private_key) + signature_bytes = sign_func(responder_private_key, response_data.dump(), self._hash_algo) + + certs = None + if self._certificate_issuer: + certs = [responder_certificate] + + return ocsp.OCSPResponse({ + 'response_status': self._response_status, + 'response_bytes': { + 'response_type': 'basic_ocsp_response', + 'response': { + 'tbs_response_data': response_data, + 'signature_algorithm': {'algorithm': signature_algorithm_id}, + 'signature': signature_bytes, + } + } + }) + +# Enums + +class ResponseStatus(enum.Enum): + successful = 'successful' + malformed_request = 'malformed_request' + internal_error = 'internal_error' + try_later = 'try_later' + sign_required = 'sign_required' + unauthorized = 'unauthorized' + + +class CertificateStatus(enum.Enum): + good = 'good' + revoked = 'revoked' + key_compromise = 'key_compromise' + ca_compromise = 'ca_compromise' + affiliation_changed = 'affiliation_changed' + superseded = 'superseded' + cessation_of_operation = 'cessation_of_operation' + certificate_hold = 'certificate_hold' + remove_from_crl = 'remove_from_crl' + privilege_withdrawn = 'privilege_withdrawn' + unknown = 'unknown' + + +# API endpoints +FAULT_REVOKED = "revoked" +FAULT_UNKNOWN = "unknown" + +class OCSPResponder: + + def __init__(self, issuer_cert: str, responder_cert: str, responder_key: str, + fault: str = None, next_update_days: int = 7): + """ + Create a new OCSPResponder instance. + + :param issuer_cert: Path to the issuer certificate. + :param responder_cert: Path to the certificate of the OCSP responder + with the `OCSP Signing` extension. + :param responder_key: Path to the private key belonging to the + responder cert. + :param validate_func: A function that - given a certificate serial - + will return the appropriate :class:`CertificateStatus` and - + depending on the status - a revocation datetime. + :param cert_retrieve_func: A function that - given a certificate serial - + will return the corresponding certificate as a string. + :param next_update_days: The ``nextUpdate`` value that will be written + into the response. Default: 7 days. + + """ + # Certs and keys + self._issuer_cert = asymmetric.load_certificate(issuer_cert) + self._responder_cert = asymmetric.load_certificate(responder_cert) + self._responder_key = asymmetric.load_private_key(responder_key) + + # Next update + self._next_update_days = next_update_days + + self._fault = fault + + # Bottle + self._app = Bottle() + + # Initialize routing + self._route() + + def _route(self): + self._app.get('/', callback=self._handle_root) + self._app.get('/status/<request_data>', callback=self._handle_get) + self._app.post('/status/', callback=self._handle_post) + + def _handle_root(self): + return 'ocsp-responder' + + def _handle_get(self, request_data): + """ + An OCSP GET request contains the DER-in-base64 encoded OCSP request in the + HTTP request URL. + """ + der = base64.b64decode(request_data) + ocsp_request = self._parse_ocsp_request(der) + return self._build_http_response(ocsp_request) + + def _handle_post(self): + """ + An OCSP POST request contains the DER encoded OCSP request in the HTTP + request body. + """ + der = request.body.read() + ocsp_request = self._parse_ocsp_request(der) + return self._build_http_response(ocsp_request) + + def _fail(self, status: ResponseStatus) -> OCSPResponse: + builder = OCSPResponseBuilder(response_status=status.value) + return builder.build() + + def _parse_ocsp_request(self, request_der: bytes) -> OCSPRequest: + """ + Parse the request bytes, return an ``OCSPRequest`` instance. + """ + return OCSPRequest.load(request_der) + + def validate(self): + time = datetime(2018, 1, 1, 1, 00, 00, 00, timezone.utc) + if self._fault == FAULT_REVOKED: + return (CertificateStatus.revoked, time) + elif self._fault == FAULT_UNKNOWN: + return (CertificateStatus.unknown, None) + elif self._fault != None: + raise NotImplemented('Fault type could not be found') + return (CertificateStatus.good, time) + + def _build_ocsp_response(self, ocsp_request: OCSPRequest) -> OCSPResponse: + """ + Create and return an OCSP response from an OCSP request. + """ + # Get the certificate serial + tbs_request = ocsp_request['tbs_request'] + request_list = tbs_request['request_list'] + if len(request_list) < 1: + logger.warning('Received OCSP request with no requests') + raise NotImplemented('Empty requests not supported') + + single_request = request_list[0] # TODO: Support more than one request + req_cert = single_request['req_cert'] + serial = req_cert['serial_number'].native + + # Check certificate status + try: + certificate_status, revocation_date = self.validate() + except Exception as e: + logger.exception('Could not determine certificate status: %s', e) + return self._fail(ResponseStatus.internal_error) + + certificate_status_list = [(serial, certificate_status.value)] + + # Build the response + builder = OCSPResponseBuilder(**{ + 'response_status': ResponseStatus.successful.value, + 'certificate_status_list': certificate_status_list, + 'revocation_date': revocation_date, + }) + + # Parse extensions + for extension in tbs_request['request_extensions']: + extn_id = extension['extn_id'].native + critical = extension['critical'].native + value = extension['extn_value'].parsed + + # This variable tracks whether any unknown extensions were encountered + unknown = False + + # Handle nonce extension + if extn_id == 'nonce': + builder.nonce = value.native + + # That's all we know + else: + unknown = True + + # If an unknown critical extension is encountered (which should not + # usually happen, according to RFC 6960 4.1.2), we should throw our + # hands up in despair and run. + if unknown is True and critical is True: + logger.warning('Could not parse unknown critical extension: %r', + dict(extension.native)) + return self._fail(ResponseStatus.internal_error) + + # If it's an unknown non-critical extension, we can safely ignore it. + elif unknown is True: + logger.info('Ignored unknown non-critical extension: %r', dict(extension.native)) + + # Set certificate issuer + builder.certificate_issuer = self._issuer_cert + + # Set next update date + builder.next_update = datetime.now(timezone.utc) + timedelta(days=self._next_update_days) + + return builder.build(self._responder_key, self._responder_cert) + + def _build_http_response(self, request_der: bytes) -> HTTPResponse: + response_der = self._build_ocsp_response(request_der).dump() + return HTTPResponse( + status=200, + body=response_der, + content_type='application/ocsp-response', + ) + + def serve(self, port=8080, debug=False): + logger.info('Launching %sserver on port %d', 'debug' if debug else '', port) + self._app.run(port=port, debug=debug) |