Skip to content

Commit 6dccca7

Browse files
committed
Fix constants in rustls glue code
* Deduplicate verify flags / record-size constants * Larger "max encrypted TLS record length"
1 parent e02a7bf commit 6dccca7

3 files changed

Lines changed: 36 additions & 29 deletions

File tree

‎crates/stdlib/src/ssl.rs‎

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,28 @@ mod _ssl {
153153

154154
// Buffer sizes and limits (OpenSSL/CPython compatibility)
155155
const PEM_BUFSIZE: usize = 1024;
156+
156157
// OpenSSL: ssl/ssl_local.h
158+
const SSL3_RT_HEADER_LENGTH: usize = 5;
159+
// This is the maximum MAC (digest) size used by the SSL library. Currently
160+
// maximum of 20 is used by SHA1, but we reserve for future extension for
161+
// 512-bit hashes.
162+
const SSL3_RT_MAX_MD_SIZE: usize = 64;
163+
// Maximum plaintext length: defined by SSL/TLS standards
157164
const SSL3_RT_MAX_PLAIN_LENGTH: usize = 16384;
165+
// Maximum compression overhead: defined by SSL/TLS standards
166+
const SSL3_RT_MAX_COMPRESSED_OVERHEAD: usize = 1024;
167+
// The standards give a maximum encryption overhead of 1024 bytes. In
168+
// practice the value is lower than this. The overhead is the maximum number
169+
// of padding bytes (256) plus the mac size.
170+
const SSL3_RT_MAX_ENCRYPTED_OVERHEAD: usize = 256 + SSL3_RT_MAX_MD_SIZE;
171+
const SSL3_RT_MAX_COMPRESSED_LENGTH: usize =
172+
SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_COMPRESSED_OVERHEAD;
173+
const SSL3_RT_MAX_ENCRYPTED_LENGTH: usize =
174+
SSL3_RT_MAX_ENCRYPTED_OVERHEAD + SSL3_RT_MAX_COMPRESSED_LENGTH;
175+
pub(crate) const SSL3_RT_MAX_PACKET_SIZE: usize =
176+
SSL3_RT_MAX_ENCRYPTED_LENGTH + SSL3_RT_HEADER_LENGTH;
177+
158178
// SSL session cache size (common practice, similar to OpenSSL defaults)
159179
const SSL_SESSION_CACHE_SIZE: usize = 256;
160180

@@ -166,21 +186,26 @@ mod _ssl {
166186
#[pyattr]
167187
const CERT_REQUIRED: i32 = 2;
168188

169-
// Certificate requirements
189+
// SSL Verification Flags / Certificate requirements
170190
#[pyattr]
171191
const VERIFY_DEFAULT: i32 = 0;
172192
#[pyattr]
173193
const VERIFY_CRL_CHECK_LEAF: i32 = 4;
174194
#[pyattr]
175195
const VERIFY_CRL_CHECK_CHAIN: i32 = 12;
196+
/// VERIFY_X509_STRICT flag for RFC 5280 strict compliance
197+
/// When set, performs additional validation including AKI extension checks
176198
#[pyattr]
177-
const VERIFY_X509_STRICT: i32 = 32;
199+
pub(crate) const VERIFY_X509_STRICT: i32 = 32;
178200
#[pyattr]
179201
const VERIFY_ALLOW_PROXY_CERTS: i32 = 64;
180202
#[pyattr]
181203
const VERIFY_X509_TRUSTED_FIRST: i32 = 32768;
204+
/// VERIFY_X509_PARTIAL_CHAIN flag for partial chain validation
205+
/// When set, accept certificates if any certificate in the chain is in the trust store
206+
/// (not just root CAs). This matches OpenSSL's X509_V_FLAG_PARTIAL_CHAIN behavior.
182207
#[pyattr]
183-
const VERIFY_X509_PARTIAL_CHAIN: i32 = 0x80000;
208+
pub(crate) const VERIFY_X509_PARTIAL_CHAIN: i32 = 0x80000;
184209

185210
// Options (OpenSSL-compatible flags, mostly no-op in rustls)
186211
#[pyattr]
@@ -4316,7 +4341,7 @@ mod _ssl {
43164341
break;
43174342
}
43184343

4319-
let mut buf = vec![0u8; SSL3_RT_MAX_PLAIN_LENGTH];
4344+
let mut buf = vec![0u8; SSL3_RT_MAX_PACKET_SIZE];
43204345
let written = conn
43214346
.write_tls(&mut buf.as_mut_slice())
43224347
.map_err(|e| vm.new_os_error(format!("TLS write failed: {e}")))?;
@@ -4348,7 +4373,7 @@ mod _ssl {
43484373
}
43494374

43504375
// BIO mode: read from incoming BIO
4351-
match self.sock_recv(SSL3_RT_MAX_PLAIN_LENGTH, vm) {
4376+
match self.sock_recv(SSL3_RT_MAX_PACKET_SIZE, vm) {
43524377
Ok(bytes_obj) => {
43534378
let bytes = ArgBytesLike::try_from_object(vm, bytes_obj)?;
43544379
let data = bytes.borrow_buf();
@@ -4387,11 +4412,7 @@ mod _ssl {
43874412
///
43884413
/// Equivalent to OpenSSL's `SSL_set_read_ahead(ssl, 0)` — rustls has no
43894414
/// such knob, so we enforce record-level reads manually via peek.
4390-
fn try_read_close_notify_socket(
4391-
&self,
4392-
conn: &mut Connection,
4393-
vm: &VirtualMachine,
4394-
) -> bool {
4415+
fn try_read_close_notify_socket(&self, conn: &mut Connection, vm: &VirtualMachine) -> bool {
43954416
// Consume at most one TLS record from the socket
43964417
match self.sock_recv_at_most_one_tls_record(vm) {
43974418
Ok(data) => {

‎crates/stdlib/src/ssl/cert.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustpython_vm::{PyObjectRef, PyResult, VirtualMachine};
2222
use std::collections::HashSet;
2323
use x509_parser::prelude::*;
2424

25-
use super::compat::{VERIFY_X509_PARTIAL_CHAIN, VERIFY_X509_STRICT};
25+
use super::_ssl::{VERIFY_X509_PARTIAL_CHAIN, VERIFY_X509_STRICT};
2626

2727
// Certificate Verification Constants
2828

‎crates/stdlib/src/ssl/compat.rs‎

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,14 @@ use std::io::Read;
3535
use std::sync::Once;
3636

3737
// Import PySSLSocket from parent module
38-
use super::_ssl::PySSLSocket;
38+
use super::_ssl::{PySSLSocket, SSL3_RT_MAX_PACKET_SIZE, VERIFY_X509_STRICT};
3939

4040
// Import error types and helper functions from error module
4141
use super::error::{
4242
PySSLCertVerificationError, PySSLError, create_ssl_eof_error, create_ssl_syscall_error,
4343
create_ssl_want_read_error, create_ssl_want_write_error, create_ssl_zero_return_error,
4444
};
4545

46-
// SSL Verification Flags
47-
/// VERIFY_X509_STRICT flag for RFC 5280 strict compliance
48-
/// When set, performs additional validation including AKI extension checks
49-
pub(super) const VERIFY_X509_STRICT: i32 = 0x20;
50-
51-
/// VERIFY_X509_PARTIAL_CHAIN flag for partial chain validation
52-
/// When set, accept certificates if any certificate in the chain is in the trust store
53-
/// (not just root CAs). This matches OpenSSL's X509_V_FLAG_PARTIAL_CHAIN behavior.
54-
pub(super) const VERIFY_X509_PARTIAL_CHAIN: i32 = 0x80000;
55-
5646
// CryptoProvider Initialization:
5747

5848
/// Ensure the default CryptoProvider is installed (thread-safe, runs once)
@@ -72,10 +62,6 @@ fn ensure_default_provider() {
7262

7363
// OpenSSL Constants:
7464

75-
// OpenSSL TLS record maximum plaintext size (ssl/ssl_local.h)
76-
// #define SSL3_RT_MAX_PLAIN_LENGTH 16384
77-
const SSL3_RT_MAX_PLAIN_LENGTH: usize = 16384;
78-
7965
// OpenSSL error library codes (include/openssl/err.h)
8066
// #define ERR_LIB_SSL 20
8167
const ERR_LIB_SSL: i32 = 20;
@@ -1092,7 +1078,7 @@ fn handshake_read_data(
10921078
// detect it.
10931079
recv_at_most_one_tls_record(socket, vm)?
10941080
} else {
1095-
match socket.sock_recv(SSL3_RT_MAX_PLAIN_LENGTH, vm) {
1081+
match socket.sock_recv(SSL3_RT_MAX_PACKET_SIZE, vm) {
10961082
Ok(d) => d,
10971083
Err(e) => {
10981084
if is_blocking_io_error(&e, vm) {
@@ -1312,7 +1298,7 @@ pub(super) fn ssl_do_handshake(
13121298
if conn.wants_write() {
13131299
// Write all pending TLS data to outgoing BIO
13141300
loop {
1315-
let mut buf = vec![0u8; SSL3_RT_MAX_PLAIN_LENGTH];
1301+
let mut buf = vec![0u8; SSL3_RT_MAX_PACKET_SIZE];
13161302
let n = match conn.write_tls(&mut buf.as_mut_slice()) {
13171303
Ok(n) => n,
13181304
Err(_) => break,
@@ -1929,7 +1915,7 @@ fn ssl_ensure_data_available(
19291915
let data = if !is_bio {
19301916
recv_at_most_one_tls_record_for_data(conn, socket, vm)?
19311917
} else {
1932-
match socket.sock_recv(2048, vm) {
1918+
match socket.sock_recv(SSL3_RT_MAX_PACKET_SIZE, vm) {
19331919
Ok(data) => data,
19341920
Err(e) => {
19351921
if is_blocking_io_error(&e, vm) {

0 commit comments

Comments
 (0)