Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Fix SSL to return deferred error on the right time
  • Loading branch information
youknowone committed Dec 9, 2025
commit 3448373429d7111daf76164472dec21f9b5ea51e
17 changes: 11 additions & 6 deletions crates/stdlib/src/ssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3323,9 +3323,6 @@ mod _ssl {
));
}

// Check for deferred certificate verification errors (TLS 1.3)
self.check_deferred_cert_error(vm)?;

// Helper function to handle return value based on buffer presence
let return_data = |data: Vec<u8>,
buffer_arg: &OptionalArg<ArgMemoryBuffer>,
Expand Down Expand Up @@ -3361,6 +3358,11 @@ mod _ssl {

match crate::ssl::compat::ssl_read(conn, &mut buf, self, vm) {
Ok(n) => {
// Drop connection guard before checking deferred error
drop(conn_guard);
// Check for deferred certificate verification errors (TLS 1.3)
// Must be checked AFTER ssl_read, as the error is set during I/O
self.check_deferred_cert_error(vm)?;
buf.truncate(n);
return_data(buf, &buffer, vm)
}
Expand Down Expand Up @@ -3445,9 +3447,6 @@ mod _ssl {
));
}

// Check for deferred certificate verification errors (TLS 1.3)
self.check_deferred_cert_error(vm)?;

let mut conn_guard = self.connection.lock();
let conn = conn_guard
.as_mut()
Expand Down Expand Up @@ -3509,6 +3508,12 @@ mod _ssl {
}
}

// Drop connection guard before checking deferred error
drop(conn_guard);
// Check for deferred certificate verification errors (TLS 1.3)
// Must be checked AFTER write completes, as the error may be set during I/O
self.check_deferred_cert_error(vm)?;

Ok(data_len)
}

Expand Down
13 changes: 7 additions & 6 deletions crates/stdlib/src/ssl/cert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1067,15 +1067,16 @@ impl ClientCertVerifier for DeferredClientCertVerifier {
.inner
.verify_client_cert(end_entity, intermediates, now);

// If verification failed, store the error for later
if result.is_err() {
let error_msg = "TLS handshake failed: received fatal alert: UnknownCA".to_string();
// If verification failed, store the error for the server's Python code
// AND return the error so rustls sends the appropriate TLS alert
if let Err(ref e) = result {
let error_msg = format!("certificate verify failed: {e}");
*self.deferred_error.write() = Some(error_msg);
// Return the error to rustls so it sends the alert to the client
return result;
}

// Always return success to allow handshake to complete
// The error will be raised during the first I/O operation
Ok(ClientCertVerified::assertion())
result
}

fn verify_tls12_signature(
Expand Down