Skip to content

Commit 666eca4

Browse files
committed
Clanker review.
1 parent e679e76 commit 666eca4

2 files changed

Lines changed: 65 additions & 1 deletion

File tree

‎Lib/test/test_ssl.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2114,6 +2114,15 @@ def test_set_ech_config(self):
21142114
self.assertRaises(ssl.SSLError, ctx.set_ech_config, config)
21152115
self.assertIsNone(ctx.set_ech_config(self.ECH_CONFIG))
21162116

2117+
@unittest.skipUnless(ssl.HAS_ECH, 'requires ECH')
2118+
def test_mixed_ech_config_versions(self):
2119+
ctx = make_test_context()
2120+
supported = self.ECH_CONFIG[2:]
2121+
unsupported = b'\xff\xff\x00\x01\x00'
2122+
for entries in (unsupported + supported, supported + unsupported):
2123+
config = len(entries).to_bytes(2, 'big') + entries
2124+
self.assertIsNone(ctx.set_ech_config(config))
2125+
21172126
@unittest.skipUnless(ssl.HAS_ECH, 'requires ECH')
21182127
def test_status_before_handshake(self):
21192128
ctx = make_test_context()
@@ -2168,6 +2177,19 @@ def test_outer_alpn_does_not_replace_inner(self):
21682177
self.assertEqual(client.selected_alpn_protocol(), 'h2')
21692178
self.assertEqual(server.selected_alpn_protocol(), 'h2')
21702179

2180+
@unittest.skipUnless(ssl.HAS_ECH, 'requires ECH')
2181+
def test_outer_alpn_without_ech_config(self):
2182+
for options in (0, ssl.OP_ECH_GREASE):
2183+
client_ctx, server_ctx, hostname = testing_context()
2184+
client_ctx.options |= options
2185+
client_ctx.set_alpn_protocols(['h2'])
2186+
client_ctx.set_outer_alpn_protocols(['http/1.1'])
2187+
server_ctx.set_alpn_protocols(['h2', 'http/1.1'])
2188+
client, server, *_ = connected_bio_pair(
2189+
client_ctx, server_ctx, hostname)
2190+
self.assertEqual(client.selected_alpn_protocol(), 'h2')
2191+
self.assertEqual(server.selected_alpn_protocol(), 'h2')
2192+
21712193
@unittest.skipUnless(ssl.HAS_ECH, 'requires ECH')
21722194
def test_grease(self):
21732195
client_ctx, server_ctx, hostname = testing_context()

‎Modules/_ssl.c‎

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,23 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
942942
return NULL;
943943
}
944944

945+
#ifdef HAVE_OPENSSL_ECH
946+
if (socket_type == PY_SSL_CLIENT) {
947+
char *inner_sni = NULL, *outer_sni = NULL;
948+
int status = SSL_ech_get1_status(self->ssl, &inner_sni, &outer_sni);
949+
OPENSSL_free(inner_sni);
950+
OPENSSL_free(outer_sni);
951+
/* OpenSSL also applies outer ALPN to ordinary and GREASE handshakes. */
952+
if ((status == SSL_ECH_STATUS_NOT_CONFIGURED ||
953+
status == SSL_ECH_STATUS_GREASE) &&
954+
SSL_ech_set1_outer_alpn_protos(self->ssl, NULL, 0) != 1) {
955+
_setSSLError(get_state_ctx(sslctx), NULL, 0, __FILE__, __LINE__);
956+
Py_DECREF(self);
957+
return NULL;
958+
}
959+
}
960+
#endif
961+
945962
if (socket_type == PY_SSL_SERVER) {
946963
#define SID_CTX "Python"
947964
/* Set the session id context (server-side only) */
@@ -5220,10 +5237,35 @@ _ssl__SSLContext_set_ech_config_impl(PySSLContext *self,
52205237
return NULL;
52215238
}
52225239
OSSL_ECHSTORE *store = NULL;
5223-
BIO *config_bio = BIO_new_mem_buf(ech_config->buf, ech_config->len);
5240+
BIO *config_bio = BIO_new(BIO_s_mem());
52245241
if (config_bio == NULL) {
52255242
goto fail;
52265243
}
5244+
const unsigned char *config = ech_config->buf;
5245+
int config_len = (int)ech_config->len;
5246+
if (config_len >= 2 && ((config[0] << 8) | config[1]) == config_len - 2) {
5247+
config += 2;
5248+
config_len -= 2;
5249+
/* OpenSSL only recognizes binary input with a supported first entry. */
5250+
while (config_len >= 4 &&
5251+
((config[0] << 8) | config[1]) != OSSL_ECH_RFC9849_VERSION) {
5252+
int entry_len = 4 + ((config[2] << 8) | config[3]);
5253+
if (entry_len > config_len) {
5254+
break;
5255+
}
5256+
config += entry_len;
5257+
config_len -= entry_len;
5258+
}
5259+
unsigned char length[2] = {
5260+
(unsigned char)(config_len >> 8), (unsigned char)config_len
5261+
};
5262+
if (BIO_write(config_bio, length, sizeof(length)) != sizeof(length)) {
5263+
goto fail;
5264+
}
5265+
}
5266+
if (BIO_write(config_bio, config, config_len) != config_len) {
5267+
goto fail;
5268+
}
52275269
store = OSSL_ECHSTORE_new(NULL, NULL);
52285270
if (store == NULL) {
52295271
goto fail;

0 commit comments

Comments
 (0)