Skip to content

Commit 229807d

Browse files
committed
Reject unavailable SSL protocol selectors
1 parent 97c4e1d commit 229807d

2 files changed

Lines changed: 41 additions & 1 deletion

File tree

graalpython/com.oracle.graal.python.test/src/tests/test_ssl.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,30 @@ def test_alpn(self):
405405
server, client = check_handshake(server_context, client_context)
406406
self.assertEqual(client.selected_alpn_protocol(), "http/1.1")
407407

408+
409+
class ProtocolSelectionTests(unittest.TestCase):
410+
411+
def check_protocol_availability_controls_selection(self, has_name, protocol_name, protocol_id):
412+
if getattr(ssl, has_name):
413+
self.assertTrue(hasattr(ssl, protocol_name))
414+
ssl.SSLContext(getattr(ssl, protocol_name))
415+
else:
416+
protocol = getattr(ssl, protocol_name, protocol_id)
417+
with self.assertRaisesRegex(ValueError, "invalid or unsupported protocol version"):
418+
ssl.SSLContext(protocol)
419+
420+
def test_single_version_availability_controls_selection(self):
421+
self.check_protocol_availability_controls_selection("HAS_SSLv3", "PROTOCOL_SSLv3", 1)
422+
self.check_protocol_availability_controls_selection("HAS_TLSv1", "PROTOCOL_TLSv1", 3)
423+
self.check_protocol_availability_controls_selection("HAS_TLSv1_1", "PROTOCOL_TLSv1_1", 4)
424+
self.check_protocol_availability_controls_selection("HAS_TLSv1_2", "PROTOCOL_TLSv1_2", 5)
425+
426+
def test_generic_protocols_keep_sslv3_disabled(self):
427+
for protocol in (ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER):
428+
with self.subTest(protocol=protocol):
429+
self.assertTrue(ssl.SSLContext(protocol).options & ssl.OP_NO_SSLv3)
430+
431+
408432
def get_cipher_list(cipher_string):
409433
context = ssl.SSLContext()
410434
context.set_ciphers(cipher_string)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLContextBuiltins.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ static PSSLContext createContext(VirtualFrame frame, Object type, int protocol,
173173
@Cached PConstructAndRaiseNode.Lazy constructAndRaiseNode,
174174
@Cached PRaiseNode raiseNode) {
175175
SSLMethod method = SSLMethod.fromPythonId(protocol);
176-
if (method == null) {
176+
if (method == null || isUnsupportedSingleVersion(method)) {
177177
throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.INVALID_OR_UNSUPPORTED_PROTOCOL_VERSION, "NULL");
178178
}
179179
try {
@@ -190,6 +190,9 @@ static PSSLContext createContext(VirtualFrame frame, Object type, int protocol,
190190
createSSLContext());
191191
long options = SSLOptions.SSL_OP_ALL;
192192
if (method != SSLMethod.SSL3) {
193+
// supportedProtocols describes runtime availability. This per-context option still keeps
194+
// generic TLS contexts from negotiating SSLv3. Only an explicit, supported SSLv3
195+
// context may leave it enabled.
193196
options |= SSLOptions.SSL_OP_NO_SSLv3;
194197
}
195198
context.setOptions(options);
@@ -201,6 +204,19 @@ static PSSLContext createContext(VirtualFrame frame, Object type, int protocol,
201204
}
202205
}
203206

207+
@TruffleBoundary
208+
private static boolean isUnsupportedSingleVersion(SSLMethod method) {
209+
if (!method.isSingleVersion()) {
210+
return false;
211+
}
212+
for (SSLProtocol supportedProtocol : SSLModuleBuiltins.getSupportedProtocols()) {
213+
if (method.allowsProtocol(supportedProtocol)) {
214+
return false;
215+
}
216+
}
217+
return true;
218+
}
219+
204220
@TruffleBoundary
205221
private static SSLContext createSSLContext() throws NoSuchAlgorithmException, KeyManagementException {
206222
SSLContext context = SSLContext.getInstance("TLS");

0 commit comments

Comments
 (0)