summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2019-11-22 17:03:28 +0000
committerevergreen <evergreen@mongodb.com>2019-11-22 17:03:28 +0000
commit8ff79f256f1e57b32edccae37dc260b342323d26 (patch)
treef083c0b59d011d1fb05b3ed2cdf46d22b0d813ba
parente19d92cb777cb87779b614c30b1ed568a6eea088 (diff)
downloadmongo-8ff79f256f1e57b32edccae37dc260b342323d26.tar.gz
SERVER-39574 Support intermediate certificates in PEMKeyFile on Windows
(cherry picked from commit aae362fc4d79c9f53c70228d1ba8b966feefaffb)
-rw-r--r--jstests/libs/intermediate-ca.pem53
-rw-r--r--jstests/libs/server-intermediate-ca.pem114
-rw-r--r--jstests/ssl/ssl_intermediate_ca.js34
-rw-r--r--src/mongo/util/net/ssl_manager_windows.cpp174
4 files changed, 262 insertions, 113 deletions
diff --git a/jstests/libs/intermediate-ca.pem b/jstests/libs/intermediate-ca.pem
new file mode 100644
index 00000000000..62ee30e9106
--- /dev/null
+++ b/jstests/libs/intermediate-ca.pem
@@ -0,0 +1,53 @@
+# Autogenerated file, do not edit.
+# Generate using jstests/ssl/x509/mkcert.py --config jstests/ssl/x509/certs.yml intermediate-ca.pem
+#
+# CA issues by the primary root CA, which then issues its own server cert.
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAloCBFNvXv0wDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCVVMxETAP
+BgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAwDgYDVQQK
+DAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxFzAVBgNVBAMMDktlcm5lbCBUZXN0
+IENBMB4XDTE5MTAxNjE3NTc0OVoXDTM5MTAxODE3NTc0OVowdTELMAkGA1UEBhMC
+VVMxETAPBgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAw
+DgYDVQQKDAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxGDAWBgNVBAMMD0ludGVy
+bWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOcrt0K/
+K8ueq9lQ9wVtA+rka82FPaHXpZkH7ii/ZJlNcDXLaJPdRb7XgAabAS3gru+Hpm/g
+kAofoL7cDmGZRAbiW0I6X5Nlmjh4/0E6RxSs0urhU34m8sM3OPmAgbq7oLlFINZ6
+GbVR2RzMWhK5HPld8WApDkIVpBFbRGV7dt/LVKY34Nab9hu15WRSH3wzSHJvt8e1
+alYxaRUoE27Fk3zdHPw9Z91/XvfIThTsNXEQVOeaieyQLwoKx8tpMa/ck/mFmSkD
+nH4h37ev0ZABB04iTBfLGCpUCKd5LerYIqEu4UPp9r9czbco7twp+k8875pJ3bpV
+wMH0/jF68GTC8HsCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsF
+AAOCAQEAaL61HT6JD19Ok2LY6b5KkZ4oRhiV73l2/82X88GcV63Bl0rN6AF+W0ut
+GuHzSqcHV4qZkt9ezNoDYq41BsV4I8Cxvyaz8is956uyrzQAsVCzidZSGeq2GIfV
+9y+IRISBRdzXQHrB0ni93b16MJO1KoJxZbXcb8W9ll2URp+YEnHIrhWpDcMcHN3O
+mjoy1+WpHDXpNK2D3Xk5tT5pwxJZWRPB9wvPfTux5Vp07+Rkef9YjXL2ZZxt4vKu
+WU0HJWfK905HpbHjwFNRlbT39WWaF8VeJ2nT6OrXTpE8tDdPoeZt5u76eaWEmsf5
+gX2ClrsSmegOKT52V+2NAlKDjQkaDg==
+-----END CERTIFICATE-----
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDnK7dCvyvLnqvZ
+UPcFbQPq5GvNhT2h16WZB+4ov2SZTXA1y2iT3UW+14AGmwEt4K7vh6Zv4JAKH6C+
+3A5hmUQG4ltCOl+TZZo4eP9BOkcUrNLq4VN+JvLDNzj5gIG6u6C5RSDWehm1Udkc
+zFoSuRz5XfFgKQ5CFaQRW0Rle3bfy1SmN+DWm/YbteVkUh98M0hyb7fHtWpWMWkV
+KBNuxZN83Rz8PWfdf173yE4U7DVxEFTnmonskC8KCsfLaTGv3JP5hZkpA5x+Id+3
+r9GQAQdOIkwXyxgqVAineS3q2CKhLuFD6fa/XM23KO7cKfpPPO+aSd26VcDB9P4x
+evBkwvB7AgMBAAECggEAaEOwYXuGDk3fpqG8+IaF6NDjyouZE8EG4LHR+jDw97AU
+tz6qSV7Y0U2zYcdRzdZ0MHcXW4iGjvpa7xqjpeOR6iT4EjPv3bRKzcPNJSda3flh
+HC1LEjAQ+HmUyfvrB0UPJeEHAZWKuNxUt4d37M/vQI3di4iY9Ld8C5QFklwQbrkU
+PLRJkpZTPkrE5S+pG80NA8eTz1OjeYFOsiD9INVmD59hgsN92DmzdKqH1QIDOvvF
+SW/C+tX9+ou40lf4RZNvjBsfN87Bwdg342YuzOD3vtXjbAkfnofJiHOlayKeLrvw
+ZyA1mW3+PfscPJ6SXea/y0sbBFYm5eihb5p+g0LwUQKBgQD8CimfkYex0uBOhFwF
+7jlTSKc3dWfs/4dXEk9q8yUloo6v03YmnxkS1cF7KSWIWYCEKe++XP/lKxgRaVrL
+Hm+Y5MrrQnVEgnmy7hphyEWuSsoDcTP60ATLXIycsgxsxi46410dVoiUyHRy/Vdj
+zswQA4+j6crdszeT5+b2K63j2QKBgQDqzZt7UIeIYLhkh+mS8C2V2rKejn+7Uk9W
+9qD+czQ3G8/H1/l5AODZKOCZpLvxi7oclJJt3WE4NQmZbg/MYLzzvZ+RlLaRRtKo
+YM5/+Z6AmkKAAp9LFX9Hi3hnNgG3JJLblDSkmZnB2Ur4JyqoeiTEKzcOxHNn6U3U
+FXV5QDKGcwKBgQCPHro6GWrDqKqlC3YyC+/TgjsqO+oy43uYDxa39bBPabq6z0qV
+bdzQHD/NTzU38xMOeb3hDHBnUwxMvtXG59aZLLqp00hCChFPcPPcONyQt3l1cPAC
+aeN/E2PpixWRIwyXdgqnIT9XtWii74eTbpfkNBF6E8WWFTHnNFWrzmvlKQKBgQCO
+ynDmgieaES+xu1GZUUR3oGMFt6UIFts3CI8JjqfPZ7NpVfdZ1eXnSkukRCEjmJSa
+8uNFut53nxFyZBNpd98Q311d3DFWkdpkGVMbUoNItAcC8BVNRQp9SNz070wFw1Eo
+Ba4p91shHvLPjIoNoRIg1iMKcP+5zpDNDCu/jAHt7wKBgBmHFAbNwjBByIMBR3fh
+VAGf/3Wow5YGXUkaYPxiiSd8pmotJWFE/47NLxvIHf6zNccuDoQA4VU9GpoLZk6p
+1K+ClyU1ksSVtDKbHtzW74xnqnZZ19L404tn7FqyHW+n7YG8sqBC6IROnPnpELh0
+fxSuEbyRVRjNO6ZO3p48E0AS
+-----END PRIVATE KEY-----
diff --git a/jstests/libs/server-intermediate-ca.pem b/jstests/libs/server-intermediate-ca.pem
index 8720a52af58..8f97a1e57a7 100644
--- a/jstests/libs/server-intermediate-ca.pem
+++ b/jstests/libs/server-intermediate-ca.pem
@@ -3,73 +3,73 @@
#
# Server certificate signed by intermediate CA, including root CA in bundle.
-----BEGIN CERTIFICATE-----
-MIIDaTCCAlECBAGwTLYwDQYJKoZIhvcNAQELBQAwdTELMAkGA1UEBhMCVVMxETAP
+MIIDaTCCAlECBCLMKCQwDQYJKoZIhvcNAQELBQAwdTELMAkGA1UEBhMCVVMxETAP
BgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAwDgYDVQQK
DAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxGDAWBgNVBAMMD0ludGVybWVkaWF0
-ZSBDQTAeFw0xOTA5MjUyMzI3NDFaFw0zOTA5MjcyMzI3NDFaMH0xCzAJBgNVBAYT
+ZSBDQTAeFw0xOTEwMTYxNzU3NDlaFw0zOTEwMTgxNzU3NDlaMH0xCzAJBgNVBAYT
AlVTMREwDwYDVQQIDAhOZXcgWW9yazEWMBQGA1UEBwwNTmV3IFlvcmsgQ2l0eTEQ
MA4GA1UECgwHTW9uZ29EQjEPMA0GA1UECwwGS2VybmVsMSAwHgYDVQQDDBdTZXJ2
ZXIgVmlhIEludGVybWVkaWF0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBANDVywmF9rAMJ1npJlALHpqAiufCBvE0zoBgUPJOPE0zTxhWQ4vWhnfQjupw
-PAUGgTeUiJSsmSDPLurTi8qO05hs5BNZxEBXMt5yK2XMOBEDrZkEnJN4fXdtrhZw
-ky2CMWEyAoKIqpS4JIqO2zmvyzbPWuDat+qlbKGq8trowukN/8vG3IjlATpDQns/
-8nrgogcx+3fZ6L75LgMCh4Imb+fZtkgehdFlOuQk/9KD7dqDzzMZ6IKeqktXNeY/
-zzrdot2GUtsOV6or8UDK0GfjUOXZWKDGyiYeD5GLVfUp0NuJEsjxq1DUZTdtO7Gv
-cMCHrnygdAXjTQ3Wi+IKWNEWqC0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAiiNz
-BkbVyBN9hjEvlKQoXMAIv8onlzrNO+CCtMMGW7O4TOc/FEN1lFVvjsWxXW6K4vQ7
-IeCzxG8tR43h5kpIhtExLLHCwxiX3+zhtmTSBBpgRGynVLSxo/fOXr5ngdqHIv2f
-qK9atn4eL/hH6DyruoKf8lR7LodX92rYC907HrDcZSFi9el7WPw/Ut8U6GCn+E8/
-2sT21wuYn11UN5gKRLDv/yACe/7hYmxrI2zvfXNuYi/Xg4y0EGS4+jZhQ6db++2C
-eulQ42LNkcQ1SVYeyKzouGB5ma6eGxHufLXSWAGJuLAYQW0VwKjBVD+lsXs1x+tw
-1n9SA1x7Enyeas7w7g==
+ggEBAKCj95jJi63dCJDKyTWQAJwgLtvqwPmIvBMbYMcmrolP3tYolwkkh6c0RJdP
+UTy4gJaLZ9b9B8GuiGFatG+ZzEqCUh6AlG1lGJwdyqyP2eotpzkZJhwLGFc81DUt
+7WKhZjHikgXcAd3VMCXsjv7/axvBnc459SpsCW5heOiJ3Ap8OJIrTuD4GAWW5cfW
+GYa1v07hqXZ7SEloRE5Hm5bItnZA9+A5QNCj2a2PqK3TlrtCnDP125iYHc4W/+NO
+1V9LPKpDffdJ7slhrX69k9oV8HTQBgu7lRHKQlprW64pg6EMsw/5hpGjpZkyG9J9
+L1FYrXqsagA1E5j87JQH+SJDOEUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAPRu7
+YtgaGPx4O2IfvYoK+BsiD/55WylDp/0zxf/xipvuoPRcMgX1ORoNuQTPfeIMxlZS
+UAIRHQSjOZQkH0WL2dglqaoBhTXO6c0PUuWOUsDDwnZE8lj26Jkka6PC8d8t7gjt
+w/k2IRnhcklKOu6pNlcYi+/WGcWphmkjMRWeka0vqXab/bxF1sdeHD9bMY59QOwI
+FT0JCG8Wn0LSi6V/Ip35JV3CryBP1Jual2aCXIXEKm3m+P4NboRQTZ7zqIcJoA8S
+i2GkuHCPOhhQP2isiRRBILujcJxnRYrR7qNIqvMrmPx3va8fMrHKtWAx+bfo/EIJ
+hlU1Eyls7Xv83x3vaA==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
-MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQ1csJhfawDCdZ
-6SZQCx6agIrnwgbxNM6AYFDyTjxNM08YVkOL1oZ30I7qcDwFBoE3lIiUrJkgzy7q
-04vKjtOYbOQTWcRAVzLecitlzDgRA62ZBJyTeH13ba4WcJMtgjFhMgKCiKqUuCSK
-jts5r8s2z1rg2rfqpWyhqvLa6MLpDf/LxtyI5QE6Q0J7P/J64KIHMft32ei++S4D
-AoeCJm/n2bZIHoXRZTrkJP/Sg+3ag88zGeiCnqpLVzXmP8863aLdhlLbDleqK/FA
-ytBn41Dl2VigxsomHg+Ri1X1KdDbiRLI8atQ1GU3bTuxr3DAh658oHQF400N1ovi
-CljRFqgtAgMBAAECggEAD8rbG9FBonaI00fKWes9WTm3R2do1vzDUPn3pRs9fCkR
-Jin/2adTa+QdqqTqJQck5msZGQUkX1LLnX5558t9PN2fMcdsC+GMOz4vAfe7la3N
-hvDOVmiaNFna/F9vAdYCnfMGNZDYNX7nZIMBGQ+uMmrj2HUxy1DPMjqXOu63LqB5
-Tgl61pQ5srqP7rVBEaek5GCKWd6lucMrGSTBqWfmBSH+6cME9KOFHBUWVVjicbmg
-0L1WuYz4fh4SDdld7375gEC+zGnfvN0XQvLcv5yff6pwZtneMaPcfw/kjFUiZGoa
-j2Q9nsk6ip/05/ycEkynhMYkrhkt7oOGK7LqC6oSEQKBgQD6nZkiAyY6OKvHUyAs
-/mBdQwnhgAfyrneTnFEeh9L33gMfALyhm8apckcb0js9RO7Srj+Xdrg0wVb1A6M1
-OmVboyk6bD7OkJsv7MOn8BPK//6+QVORagiKYRhClltSuZYJaa1cC24EPdJ64Zcy
-Tb02xeluG3LThUUfbZ2U7Yb6TwKBgQDVUmZL+ohsJfFt3hfuc/4slz8aDNf5WWV1
-Zn5v5CMmXvbSLXSNp3EFlbRxM8W0YBBpspxb2RZ+4k0bSOrrxzCHu5c0RDZscfSL
-mv6zzrnfwwq92DRbDwnW2+wskO2NIsAODA/GvyhTI6AmQ+3iWl9YcMrIiaVeEa/3
-wW/7ISCiwwKBgDtoBjegxXwBmP6LvtHLjq4syPfSMJAfOSsdX8E78w9caiL8OrqY
-QXRDKYX3xKEWaQI52csekjW3KtSzgwmICSS6vXgi1pSChLbMieiSKS7ylcElnRiY
-KOQcdfK6z3UBlwYuLbDm6LJKsUz9kqiS8uo76cR27zYinisAAd2enGNTAoGBAJsA
-mJw0mtQabecrLbByUAoOjCddlcD1GCfKJa0f0/qZnjbyGHKlbBZmxQpMWCfMdaCX
-y81hXFsuDGD7BtfzkGvP/vpXZkQ+OTcHlHMKjzzr9+4iH0jbEIcyndV0KWgYC/0o
-/n2ngKGIjWHAkiWbDRSyQGaeva4wo/AeekO7un8JAoGBAMadYGAhQQhcvG5AYQYl
-6kN/xE7qjL6fewxd7EteBvPqzeL6grwAKAjOOjFA8OvAzwOxx8r024ICo49SYTmy
-OUO6bGWRzLvzRSWZKnN7ey7ZM4Z2avrG8gys9FUQOajPmIlFItulVEyG9GbKvMum
-njdOAl9FqeGcVp2CuM+bI+w9
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCgo/eYyYut3QiQ
+ysk1kACcIC7b6sD5iLwTG2DHJq6JT97WKJcJJIenNESXT1E8uICWi2fW/QfBrohh
+WrRvmcxKglIegJRtZRicHcqsj9nqLac5GSYcCxhXPNQ1Le1ioWYx4pIF3AHd1TAl
+7I7+/2sbwZ3OOfUqbAluYXjoidwKfDiSK07g+BgFluXH1hmGtb9O4al2e0hJaERO
+R5uWyLZ2QPfgOUDQo9mtj6it05a7Qpwz9duYmB3OFv/jTtVfSzyqQ333Se7JYa1+
+vZPaFfB00AYLu5URykJaa1uuKYOhDLMP+YaRo6WZMhvSfS9RWK16rGoANROY/OyU
+B/kiQzhFAgMBAAECggEAYNydpj4ZADwgNxZfnvF2vK1XM/noZE6DgU3n3A3B/j/v
+0NhmwfeJ6FNG7KnCBUgHGT9z3Jlz/OBdkb5cwFJPcboFBClp1lC4NyJrnAOdVWwz
+weUdKpmyEqA2IN7RncBOW9QPUoMniPhMcQGj87RVhEYJ/ljKMMs2IJ2bhzPhP1xV
+MK/NJ6cT680MwZTzWWIPYT30Pv6IDm5INjb+AG4PuzDXTx28GsCw2z9RnlH8aSdu
+9qSNEoh4oXef4ny2niKa+fwRgTrkUYyljML34301dx6MclsMz0k9SprGrB2dPAxg
+IV3pRO3rqS6oEZKjyyXHPV45Q/AAm3tsP5aZCJm9fQKBgQDO6Qj5UpJT1PZcpTLW
+UY1l9N9GWDlRCCpprQYKwOWK6H9Pb5ptBYzGrIjC9YmX9hYjL7wOiznSsCO4zv8d
+1AR56A3APzD2iQQTyRkY9lr0CbtOSeYyg6MHQOVY8T8E/gw5M6SakLeB9ZwOLjxl
+fwu7gKAYmZi+h11R7f5EP3HZdwKBgQDGwK0RAC+fxtGFOY9CGqwG5rom3VPvpKd9
+gjlekXbGguA2Z21y6IdMjpTcrbnCX3DRNedpq1LH0r4xW2zrjV4P7g3j7qeSQwqW
+exHLvcfEkUAjPpaE64sC3qYgwJSwNdVWG+ikBmvT4oobFsOZzL6563Md54Tlo+bN
+MQ4dPhCrIwKBgFR4OGyotAo7X9RUsNtj8cjU3i32qHeXUNFRjKzpMQyze/3u/ulR
+IbaeCzskSGbcVQ9KVojNd+62b+7ruqTvwGAQR0Tbx15uc1ase22AbYNBUdFVRAAN
+U4oLiVX1LxgXqt/TYHilafVJUstLPubkpeKHUVSZqAzocEWZVnuANzdjAoGAFvUW
+iIou9hOvC+Z0J7yQ9lMcWXTjRyELv7GVEtlWkON5Jo+X0tgNGMi3ZS4j8NG5ZFEH
+o+sIKtCq62SWFjdEEC79J8DfVkOsK2mXyqLnOktUzz1hgYT7j59MLShRhHETbVjX
+7GpZdiYKscpVWaSOu0b5CxE9BpGCDV2HNdV/c2UCgYEArnS54agkV1qQ6AbMHdkD
+qAiDqOosDDzxgnEz422r5S9CGZ4n8uu9PGhb8NtlLxxxfKnArFGOiHmV0aPULUNp
+tX+vq4JC+1gyStUdwYkrhN48eG1KUFiAqcfEFxBgvdtpKxeOd+O5SKD/ceqJO7+3
+Z826BiCbw4nJAFNHmbNr6iw=
-----END PRIVATE KEY-----
-# Certificate from ca.pem
+# Certificate from intermediate-ca.pem
-----BEGIN CERTIFICATE-----
-MIIDdDCCAlwCBBmRIxIwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCVVMxETAP
+MIIDcjCCAloCBFNvXv0wDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCVVMxETAP
BgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAwDgYDVQQK
DAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxFzAVBgNVBAMMDktlcm5lbCBUZXN0
-IENBMB4XDTE5MDkyNTIzMjczOVoXDTM5MDkyNzIzMjczOVowdDELMAkGA1UEBhMC
+IENBMB4XDTE5MTAxNjE3NTc0OVoXDTM5MTAxODE3NTc0OVowdTELMAkGA1UEBhMC
VVMxETAPBgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAw
-DgYDVQQKDAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxFzAVBgNVBAMMDktlcm5l
-bCBUZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAupVkx8+n
-AqzsANKwNPeCYlf2q0WgF4kSUMNJdpmMelrr7hh7EOnAU0hTAQx9BKTEbExeCzH6
-OArFNGjewjWVXwaOpCjK8FMvK6/lGVEpmoHNF9XuiQVmaQ4bJD6rC73YjpgNIPeL
-5PyoFLEZv+X2cRBPpTcSRcf87tk8HL7v0eyk1JBhkeKK68SYdWwZlHaa1jqwmliW
-WvVMkHVH3lx0VOgQwWtOgs0K1zpcZ0sH5MGpYRQOiidIRZj3PkKeTPQe2D6VQQtv
-2yDs9dWfCxJJP9QiWclL2rF/xqlFSNEIfNZpZhk6I1DHQpA2uyJfzRH62pFasJuB
-CVh5Tr0EDoVreQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
-CwUAA4IBAQARdNCYYWxi2fyhJwzGHwIT261d/pTlOSYLlm84c72aEneFUnfp8/H5
-JjuFbnhiX+5+h3M7eDQhra9s+H3vKr7o38EIVf5OKXvpNLwv1UUmomBvKqccioYh
-bxrfwCzfBRuUmW05kcAVn8iKovqyxL7npEZbckwtT+BqZ4kOL4Uzre+S1HMx0zOu
-xulSYA/sBoJ2BB93ZIAqB+f/+InS9yggzyhhaQqS7QEl1L4nZE4Oy0jKcxdCzysm
-TqiyH+OI5SVRTfXh4XvHmdWBBaQyaTmQzXYUxUi7jg1jEAiebCGrEJv9plwq4KfC
-cze9NLBjaXR3GzonT8kICyVT/0UvhuJg
+DgYDVQQKDAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxGDAWBgNVBAMMD0ludGVy
+bWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOcrt0K/
+K8ueq9lQ9wVtA+rka82FPaHXpZkH7ii/ZJlNcDXLaJPdRb7XgAabAS3gru+Hpm/g
+kAofoL7cDmGZRAbiW0I6X5Nlmjh4/0E6RxSs0urhU34m8sM3OPmAgbq7oLlFINZ6
+GbVR2RzMWhK5HPld8WApDkIVpBFbRGV7dt/LVKY34Nab9hu15WRSH3wzSHJvt8e1
+alYxaRUoE27Fk3zdHPw9Z91/XvfIThTsNXEQVOeaieyQLwoKx8tpMa/ck/mFmSkD
+nH4h37ev0ZABB04iTBfLGCpUCKd5LerYIqEu4UPp9r9czbco7twp+k8875pJ3bpV
+wMH0/jF68GTC8HsCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsF
+AAOCAQEAaL61HT6JD19Ok2LY6b5KkZ4oRhiV73l2/82X88GcV63Bl0rN6AF+W0ut
+GuHzSqcHV4qZkt9ezNoDYq41BsV4I8Cxvyaz8is956uyrzQAsVCzidZSGeq2GIfV
+9y+IRISBRdzXQHrB0ni93b16MJO1KoJxZbXcb8W9ll2URp+YEnHIrhWpDcMcHN3O
+mjoy1+WpHDXpNK2D3Xk5tT5pwxJZWRPB9wvPfTux5Vp07+Rkef9YjXL2ZZxt4vKu
+WU0HJWfK905HpbHjwFNRlbT39WWaF8VeJ2nT6OrXTpE8tDdPoeZt5u76eaWEmsf5
+gX2ClrsSmegOKT52V+2NAlKDjQkaDg==
-----END CERTIFICATE-----
diff --git a/jstests/ssl/ssl_intermediate_ca.js b/jstests/ssl/ssl_intermediate_ca.js
index 887127d6a73..048bdf782ec 100644
--- a/jstests/ssl/ssl_intermediate_ca.js
+++ b/jstests/ssl/ssl_intermediate_ca.js
@@ -6,12 +6,6 @@
load('jstests/ssl/libs/ssl_helpers.js');
-if (determineSSLProvider() === 'windows') {
- // FIXME: SERVER-39574
- print("Skipping test with windows SChannel pending SERVER-39574");
- return;
-}
-
// server-intermediate-ca was signed by ca.pem, not trusted-ca.pem
const VALID_CA = 'jstests/libs/ca.pem';
const INVALID_CA = 'jstests/libs/trusted-ca.pem';
@@ -34,4 +28,32 @@ runTest(VALID_CA, VALID_CA);
// Alternate CA mode, only the inbound CA is valid.
runTest(VALID_CA, INVALID_CA);
+
+// Validate we can make a connection from the shell with the intermediate certs
+{
+ const mongod = MongoRunner.runMongod({
+ sslMode: 'requireSSL',
+ sslAllowConnectionsWithoutCertificates: '',
+ sslPEMKeyFile: 'jstests/libs/server.pem',
+ sslCAFile: VALID_CA,
+ });
+ assert(mongod);
+ assert.eq(mongod.getDB('admin').system.users.find({}).toArray(), []);
+
+ const smoke = runMongoProgram("mongo",
+ "--host",
+ "localhost",
+ "--port",
+ mongod.port,
+ "--ssl",
+ "--sslCAFile",
+ VALID_CA,
+ "--sslPEMKeyFile",
+ "jstests/libs/server-intermediate-ca.pem",
+ "--eval",
+ "1;");
+ assert.eq(smoke, 0, "Could not connect with intermediate certificate");
+
+ MongoRunner.stopMongod(mongod);
+}
})();
diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp
index 36e552c6e17..65a72ce2573 100644
--- a/src/mongo/util/net/ssl_manager_windows.cpp
+++ b/src/mongo/util/net/ssl_manager_windows.cpp
@@ -685,6 +685,73 @@ StatusWith<std::vector<BYTE>> decodeObject(const char* structType,
return std::move(binaryBlobBuf);
}
+StatusWith<std::vector<UniqueCertificate>> readCAPEMBuffer(StringData buffer) {
+ std::vector<UniqueCertificate> certs;
+
+ // Search the buffer for the various strings that make up a PEM file
+ size_t pos = 0;
+ bool found_one = false;
+
+ while (pos < buffer.size()) {
+ auto swBlob = findPEMBlob(buffer, "CERTIFICATE"_sd, pos, pos != 0);
+
+ // We expect to find at least one certificate
+ if (!swBlob.isOK()) {
+ if (found_one) {
+ return Status::OK();
+ }
+
+ return swBlob.getStatus();
+ }
+
+ found_one = true;
+
+ auto blobBuf = swBlob.getValue();
+
+ if (blobBuf.empty()) {
+ return {std::move(certs)};
+ }
+
+ pos = (blobBuf.rawData() + blobBuf.size()) - buffer.rawData();
+
+ auto swCert = decodePEMBlob(blobBuf);
+ if (!swCert.isOK()) {
+ return swCert.getStatus();
+ }
+
+ auto certBuf = swCert.getValue();
+
+ PCCERT_CONTEXT cert =
+ CertCreateCertificateContext(X509_ASN_ENCODING, certBuf.data(), certBuf.size());
+ if (cert == NULL) {
+ DWORD gle = GetLastError();
+ return Status(ErrorCodes::InvalidSSLConfiguration,
+ str::stream() << "CertCreateCertificateContext failed to decode cert: "
+ << errnoWithDescription(gle));
+ }
+
+ certs.emplace_back(cert);
+ }
+
+ return {std::move(certs)};
+}
+
+Status addCertificatesToStore(HCERTSTORE certStore, std::vector<UniqueCertificate>& certificates) {
+ for (auto& cert : certificates) {
+ BOOL ret =
+ CertAddCertificateContextToStore(certStore, cert.get(), CERT_STORE_ADD_NEW, NULL);
+
+ if (!ret) {
+ DWORD gle = GetLastError();
+ return Status(ErrorCodes::InvalidSSLConfiguration,
+ str::stream() << "CertAddCertificateContextToStore Failed "
+ << errnoWithDescription(gle));
+ }
+ }
+
+ return Status::OK();
+}
+
// Read a Certificate PEM file with a private key from disk
StatusWith<UniqueCertificateWithPrivateKey> readCertPEMFile(StringData fileName,
StringData password) {
@@ -715,10 +782,18 @@ StatusWith<UniqueCertificateWithPrivateKey> readCertPEMFile(StringData fileName,
// file.
auto secondPublicKeyBlobPosition =
buf.find("CERTIFICATE", (publicKeyBlob.rawData() + publicKeyBlob.size()) - buf.data());
+ std::vector<UniqueCertificate> extraCertificates;
if (secondPublicKeyBlobPosition != std::string::npos) {
- return Status(ErrorCodes::InvalidSSLConfiguration,
- str::stream() << "Certificate PEM files should only have one certificate, "
- "intermediate CA certificates belong in the CA file.");
+ // Read in extra certificates
+ StringData extraCertificatesBuffer =
+ StringData(buf).substr(secondPublicKeyBlobPosition - ("-----BEGIN "_sd).size());
+
+ auto swExtraCertificates = readCAPEMBuffer(extraCertificatesBuffer);
+ if (!swExtraCertificates.isOK()) {
+ return swExtraCertificates.getStatus();
+ }
+
+ extraCertificates = std::move(swExtraCertificates.getValue());
}
auto swCert = decodePEMBlob(publicKeyBlob);
@@ -738,6 +813,32 @@ StatusWith<UniqueCertificateWithPrivateKey> readCertPEMFile(StringData fileName,
<< errnoWithDescription(gle));
}
+ UniqueCertificate tempCertHolder(cert);
+
+ HCERTSTORE store = CertOpenStore(
+ CERT_STORE_PROV_MEMORY, 0, NULL, CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL);
+ if (store == NULL) {
+ DWORD gle = GetLastError();
+ return Status(ErrorCodes::InvalidSSLConfiguration,
+ str::stream() << "CertOpenStore failed to create memory store: "
+ << errnoWithDescription(gle));
+ }
+
+ UniqueCertStore storeHolder(store);
+
+ // Add the newly created certificate to the memory store, this makes a copy
+ BOOL ret = CertAddCertificateContextToStore(store, cert, CERT_STORE_ADD_NEW, NULL);
+
+ if (!ret) {
+ DWORD gle = GetLastError();
+ return Status(ErrorCodes::InvalidSSLConfiguration,
+ str::stream() << "CertAddCertificateContextToStore Memory Failed "
+ << errnoWithDescription(gle));
+ }
+
+ // Get the certificate from the store so we attach the private key to the cert in the store
+ cert = CertEnumCertificatesInStore(store, NULL);
+
UniqueCertificate certHolder(cert);
std::vector<uint8_t> privateKey;
@@ -807,7 +908,6 @@ StatusWith<UniqueCertificateWithPrivateKey> readCertPEMFile(StringData fileName,
HCRYPTPROV hProv;
std::wstring wstr;
- BOOL ret;
// Create the right Crypto context depending on whether we running in a server or outside.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa375195(v=vs.85).aspx
@@ -902,7 +1002,10 @@ StatusWith<UniqueCertificateWithPrivateKey> readCertPEMFile(StringData fileName,
<< errnoWithDescription(gle));
}
- return UniqueCertificateWithPrivateKey(std::move(certHolder), std::move(cryptProvider));
+ // Add the extra certificates into the same certificate store as the certificate
+ addCertificatesToStore(certHolder->hCertStore, extraCertificates);
+
+ return UniqueCertificateWithPrivateKey{std::move(certHolder), std::move(cryptProvider)};
}
Status readCAPEMFile(HCERTSTORE certStore, StringData fileName) {
@@ -914,53 +1017,15 @@ Status readCAPEMFile(HCERTSTORE certStore, StringData fileName) {
std::string buf = std::move(swBuf.getValue());
- // Search the buffer for the various strings that make up a PEM file
- size_t pos = 0;
-
- while (pos < buf.size()) {
- auto swBlob = findPEMBlob(buf, "CERTIFICATE"_sd, pos, pos != 0);
-
- // We expect to find at least one certificate
- if (!swBlob.isOK()) {
- return swBlob.getStatus();
- }
-
- auto blobBuf = swBlob.getValue();
-
- if (blobBuf.empty()) {
- return Status::OK();
- }
-
- pos = (blobBuf.rawData() + blobBuf.size()) - buf.data();
-
- auto swCert = decodePEMBlob(blobBuf);
- if (!swCert.isOK()) {
- return swCert.getStatus();
- }
-
- auto certBuf = swCert.getValue();
-
- PCCERT_CONTEXT cert =
- CertCreateCertificateContext(X509_ASN_ENCODING, certBuf.data(), certBuf.size());
- if (cert == NULL) {
- DWORD gle = GetLastError();
- return Status(ErrorCodes::InvalidSSLConfiguration,
- str::stream() << "CertCreateCertificateContext failed to decode cert: "
- << errnoWithDescription(gle));
- }
- UniqueCertificate certHolder(cert);
-
- BOOL ret = CertAddCertificateContextToStore(certStore, cert, CERT_STORE_ADD_NEW, NULL);
- if (!ret) {
- DWORD gle = GetLastError();
- return Status(ErrorCodes::InvalidSSLConfiguration,
- str::stream() << "CertAddCertificateContextToStore Failed "
- << errnoWithDescription(gle));
- }
+ auto swCerts = readCAPEMBuffer(buf);
+ if (!swCerts.isOK()) {
+ return swCerts.getStatus();
}
- return Status::OK();
+ auto certs = std::move(swCerts.getValue());
+
+ return addCertificatesToStore(certStore, certs);
}
Status readCRLPEMFile(HCERTSTORE certStore, StringData fileName) {
@@ -974,15 +1039,22 @@ Status readCRLPEMFile(HCERTSTORE certStore, StringData fileName) {
// Search the buffer for the various strings that make up a PEM file
size_t pos = 0;
+ bool found_one = false;
while (pos < buf.size()) {
auto swBlob = findPEMBlob(buf, "X509 CRL"_sd, pos, pos != 0);
// We expect to find at least one CRL
if (!swBlob.isOK()) {
+ if (found_one) {
+ return Status::OK();
+ }
+
return swBlob.getStatus();
}
+ found_one = true;
+
auto blobBuf = swBlob.getValue();
if (blobBuf.empty()) {
@@ -1294,6 +1366,8 @@ Status SSLManagerWindows::initSSLContext(SCHANNEL_CRED* cred,
| SCH_CRED_REVOCATION_CHECK_CHAIN // Check certificate revocation
| SCH_CRED_NO_SERVERNAME_CHECK // Do not validate server name against cert
| SCH_CRED_NO_DEFAULT_CREDS // No Default Certificate
+ | SCH_CRED_MEMORY_STORE_CERT // Read intermediate certificates from memory store
+ // associated with client certificate.
| SCH_CRED_MANUAL_CRED_VALIDATION; // Validate Certificate Manually
}
@@ -1622,7 +1696,7 @@ Status validatePeerCertificate(const std::string& remoteHost,
BOOL ret = CertGetCertificateChain(certChainEngine,
cert,
NULL,
- NULL,
+ cert->hCertStore,
&certChainPara,
CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
NULL,