Skip to content

Commit 64c304a

Browse files
authored
refactor(ext/tls): use concrete error types (denoland#26174)
1 parent 2ac699f commit 64c304a

File tree

7 files changed

+79
-54
lines changed

7 files changed

+79
-54
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/net/ops_tls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ pub fn op_tls_cert_resolver_resolve_error(
250250
#[string] sni: String,
251251
#[string] error: String,
252252
) {
253-
lookup.resolve(sni, Err(anyhow!(error)))
253+
lookup.resolve(sni, Err(error))
254254
}
255255

256256
#[op2]

ext/tls/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ rustls-pemfile.workspace = true
2121
rustls-tokio-stream.workspace = true
2222
rustls-webpki.workspace = true
2323
serde.workspace = true
24+
thiserror.workspace = true
2425
tokio.workspace = true
2526
webpki-roots.workspace = true

ext/tls/lib.rs

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,12 @@ pub use rustls_tokio_stream::*;
99
pub use webpki;
1010
pub use webpki_roots;
1111

12-
use deno_core::anyhow::anyhow;
13-
use deno_core::error::custom_error;
14-
use deno_core::error::AnyError;
15-
1612
use rustls::client::danger::HandshakeSignatureValid;
1713
use rustls::client::danger::ServerCertVerified;
1814
use rustls::client::danger::ServerCertVerifier;
1915
use rustls::client::WebPkiServerVerifier;
2016
use rustls::ClientConfig;
2117
use rustls::DigitallySignedStruct;
22-
use rustls::Error;
2318
use rustls::RootCertStore;
2419
use rustls_pemfile::certs;
2520
use rustls_pemfile::ec_private_keys;
@@ -35,12 +30,30 @@ use std::sync::Arc;
3530
mod tls_key;
3631
pub use tls_key::*;
3732

33+
#[derive(Debug, thiserror::Error)]
34+
pub enum TlsError {
35+
#[error(transparent)]
36+
Rustls(#[from] rustls::Error),
37+
#[error("Unable to add pem file to certificate store: {0}")]
38+
UnableAddPemFileToCert(std::io::Error),
39+
#[error("Unable to decode certificate")]
40+
CertInvalid,
41+
#[error("No certificates found in certificate data")]
42+
CertsNotFound,
43+
#[error("No keys found in key data")]
44+
KeysNotFound,
45+
#[error("Unable to decode key")]
46+
KeyDecode,
47+
}
48+
3849
/// Lazily resolves the root cert store.
3950
///
4051
/// This was done because the root cert store is not needed in all cases
4152
/// and takes a bit of time to initialize.
4253
pub trait RootCertStoreProvider: Send + Sync {
43-
fn get_or_try_init(&self) -> Result<&RootCertStore, AnyError>;
54+
fn get_or_try_init(
55+
&self,
56+
) -> Result<&RootCertStore, deno_core::error::AnyError>;
4457
}
4558

4659
// This extension has no runtime apis, it only exports some shared native functions.
@@ -77,7 +90,7 @@ impl ServerCertVerifier for NoCertificateVerification {
7790
server_name: &rustls::pki_types::ServerName<'_>,
7891
ocsp_response: &[u8],
7992
now: rustls::pki_types::UnixTime,
80-
) -> Result<ServerCertVerified, Error> {
93+
) -> Result<ServerCertVerified, rustls::Error> {
8194
if self.ic_allowlist.is_empty() {
8295
return Ok(ServerCertVerified::assertion());
8396
}
@@ -89,7 +102,9 @@ impl ServerCertVerifier for NoCertificateVerification {
89102
_ => {
90103
// NOTE(bartlomieju): `ServerName` is a non-exhaustive enum
91104
// so we have this catch all errors here.
92-
return Err(Error::General("Unknown `ServerName` variant".to_string()));
105+
return Err(rustls::Error::General(
106+
"Unknown `ServerName` variant".to_string(),
107+
));
93108
}
94109
};
95110
if self.ic_allowlist.contains(&dns_name_or_ip_address) {
@@ -110,7 +125,7 @@ impl ServerCertVerifier for NoCertificateVerification {
110125
message: &[u8],
111126
cert: &rustls::pki_types::CertificateDer,
112127
dss: &DigitallySignedStruct,
113-
) -> Result<HandshakeSignatureValid, Error> {
128+
) -> Result<HandshakeSignatureValid, rustls::Error> {
114129
if self.ic_allowlist.is_empty() {
115130
return Ok(HandshakeSignatureValid::assertion());
116131
}
@@ -126,7 +141,7 @@ impl ServerCertVerifier for NoCertificateVerification {
126141
message: &[u8],
127142
cert: &rustls::pki_types::CertificateDer,
128143
dss: &DigitallySignedStruct,
129-
) -> Result<HandshakeSignatureValid, Error> {
144+
) -> Result<HandshakeSignatureValid, rustls::Error> {
130145
if self.ic_allowlist.is_empty() {
131146
return Ok(HandshakeSignatureValid::assertion());
132147
}
@@ -178,7 +193,7 @@ pub fn create_client_config(
178193
unsafely_ignore_certificate_errors: Option<Vec<String>>,
179194
maybe_cert_chain_and_key: TlsKeys,
180195
socket_use: SocketUse,
181-
) -> Result<ClientConfig, AnyError> {
196+
) -> Result<ClientConfig, TlsError> {
182197
if let Some(ic_allowlist) = unsafely_ignore_certificate_errors {
183198
let client_config = ClientConfig::builder()
184199
.dangerous()
@@ -214,10 +229,7 @@ pub fn create_client_config(
214229
root_cert_store.add(cert)?;
215230
}
216231
Err(e) => {
217-
return Err(anyhow!(
218-
"Unable to add pem file to certificate store: {}",
219-
e
220-
));
232+
return Err(TlsError::UnableAddPemFileToCert(e));
221233
}
222234
}
223235
}
@@ -255,74 +267,61 @@ fn add_alpn(client: &mut ClientConfig, socket_use: SocketUse) {
255267

256268
pub fn load_certs(
257269
reader: &mut dyn BufRead,
258-
) -> Result<Vec<CertificateDer<'static>>, AnyError> {
270+
) -> Result<Vec<CertificateDer<'static>>, TlsError> {
259271
let certs: Result<Vec<_>, _> = certs(reader).collect();
260272

261-
let certs = certs
262-
.map_err(|_| custom_error("InvalidData", "Unable to decode certificate"))?;
273+
let certs = certs.map_err(|_| TlsError::CertInvalid)?;
263274

264275
if certs.is_empty() {
265-
return Err(cert_not_found_err());
276+
return Err(TlsError::CertsNotFound);
266277
}
267278

268279
Ok(certs)
269280
}
270281

271-
fn key_decode_err() -> AnyError {
272-
custom_error("InvalidData", "Unable to decode key")
273-
}
274-
275-
fn key_not_found_err() -> AnyError {
276-
custom_error("InvalidData", "No keys found in key data")
277-
}
278-
279-
fn cert_not_found_err() -> AnyError {
280-
custom_error("InvalidData", "No certificates found in certificate data")
281-
}
282-
283282
/// Starts with -----BEGIN RSA PRIVATE KEY-----
284283
fn load_rsa_keys(
285284
mut bytes: &[u8],
286-
) -> Result<Vec<PrivateKeyDer<'static>>, AnyError> {
285+
) -> Result<Vec<PrivateKeyDer<'static>>, TlsError> {
287286
let keys: Result<Vec<_>, _> = rsa_private_keys(&mut bytes).collect();
288-
let keys = keys.map_err(|_| key_decode_err())?;
287+
let keys = keys.map_err(|_| TlsError::KeyDecode)?;
289288
Ok(keys.into_iter().map(PrivateKeyDer::Pkcs1).collect())
290289
}
291290

292291
/// Starts with -----BEGIN EC PRIVATE KEY-----
293292
fn load_ec_keys(
294293
mut bytes: &[u8],
295-
) -> Result<Vec<PrivateKeyDer<'static>>, AnyError> {
294+
) -> Result<Vec<PrivateKeyDer<'static>>, TlsError> {
296295
let keys: Result<Vec<_>, std::io::Error> =
297296
ec_private_keys(&mut bytes).collect();
298-
let keys2 = keys.map_err(|_| key_decode_err())?;
297+
let keys2 = keys.map_err(|_| TlsError::KeyDecode)?;
299298
Ok(keys2.into_iter().map(PrivateKeyDer::Sec1).collect())
300299
}
301300

302301
/// Starts with -----BEGIN PRIVATE KEY-----
303302
fn load_pkcs8_keys(
304303
mut bytes: &[u8],
305-
) -> Result<Vec<PrivateKeyDer<'static>>, AnyError> {
304+
) -> Result<Vec<PrivateKeyDer<'static>>, TlsError> {
306305
let keys: Result<Vec<_>, std::io::Error> =
307306
pkcs8_private_keys(&mut bytes).collect();
308-
let keys2 = keys.map_err(|_| key_decode_err())?;
307+
let keys2 = keys.map_err(|_| TlsError::KeyDecode)?;
309308
Ok(keys2.into_iter().map(PrivateKeyDer::Pkcs8).collect())
310309
}
311310

312311
fn filter_invalid_encoding_err(
313-
to_be_filtered: Result<HandshakeSignatureValid, Error>,
314-
) -> Result<HandshakeSignatureValid, Error> {
312+
to_be_filtered: Result<HandshakeSignatureValid, rustls::Error>,
313+
) -> Result<HandshakeSignatureValid, rustls::Error> {
315314
match to_be_filtered {
316-
Err(Error::InvalidCertificate(rustls::CertificateError::BadEncoding)) => {
317-
Ok(HandshakeSignatureValid::assertion())
318-
}
315+
Err(rustls::Error::InvalidCertificate(
316+
rustls::CertificateError::BadEncoding,
317+
)) => Ok(HandshakeSignatureValid::assertion()),
319318
res => res,
320319
}
321320
}
322321

323322
pub fn load_private_keys(
324323
bytes: &[u8],
325-
) -> Result<Vec<PrivateKeyDer<'static>>, AnyError> {
324+
) -> Result<Vec<PrivateKeyDer<'static>>, TlsError> {
326325
let mut keys = load_rsa_keys(bytes)?;
327326

328327
if keys.is_empty() {
@@ -334,7 +333,7 @@ pub fn load_private_keys(
334333
}
335334

336335
if keys.is_empty() {
337-
return Err(key_not_found_err());
336+
return Err(TlsError::KeysNotFound);
338337
}
339338

340339
Ok(keys)

ext/tls/tls_key.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
//! key lookup can handle closing one end of the pair, in which case they will just
1212
//! attempt to clean up the associated resources.
1313
14-
use deno_core::anyhow::anyhow;
15-
use deno_core::error::AnyError;
1614
use deno_core::futures::future::poll_fn;
1715
use deno_core::futures::future::Either;
1816
use deno_core::futures::FutureExt;
@@ -33,7 +31,19 @@ use tokio::sync::oneshot;
3331
use webpki::types::CertificateDer;
3432
use webpki::types::PrivateKeyDer;
3533

36-
type ErrorType = Rc<AnyError>;
34+
#[derive(Debug, thiserror::Error)]
35+
pub enum TlsKeyError {
36+
#[error(transparent)]
37+
Rustls(#[from] rustls::Error),
38+
#[error("Failed: {0}")]
39+
Failed(ErrorType),
40+
#[error(transparent)]
41+
JoinError(#[from] tokio::task::JoinError),
42+
#[error(transparent)]
43+
RecvError(#[from] tokio::sync::broadcast::error::RecvError),
44+
}
45+
46+
type ErrorType = Arc<Box<str>>;
3747

3848
/// A TLS certificate/private key pair.
3949
/// see https://docs.rs/rustls-pki-types/latest/rustls_pki_types/#cloning-private-keys
@@ -114,7 +124,7 @@ impl TlsKeyResolver {
114124
&self,
115125
sni: String,
116126
alpn: Vec<Vec<u8>>,
117-
) -> Result<Arc<ServerConfig>, AnyError> {
127+
) -> Result<Arc<ServerConfig>, TlsKeyError> {
118128
let key = self.resolve(sni).await?;
119129

120130
let mut tls_config = ServerConfig::builder()
@@ -183,7 +193,7 @@ impl TlsKeyResolver {
183193
pub fn resolve(
184194
&self,
185195
sni: String,
186-
) -> impl Future<Output = Result<TlsKey, AnyError>> {
196+
) -> impl Future<Output = Result<TlsKey, TlsKeyError>> {
187197
let mut cache = self.inner.cache.borrow_mut();
188198
let mut recv = match cache.get(&sni) {
189199
None => {
@@ -194,7 +204,7 @@ impl TlsKeyResolver {
194204
}
195205
Some(TlsKeyState::Resolving(recv)) => recv.resubscribe(),
196206
Some(TlsKeyState::Resolved(res)) => {
197-
return Either::Left(ready(res.clone().map_err(|_| anyhow!("Failed"))));
207+
return Either::Left(ready(res.clone().map_err(TlsKeyError::Failed)));
198208
}
199209
};
200210
drop(cache);
@@ -212,7 +222,7 @@ impl TlsKeyResolver {
212222
// Someone beat us to it
213223
}
214224
}
215-
res.map_err(|_| anyhow!("Failed"))
225+
res.map_err(TlsKeyError::Failed)
216226
});
217227
Either::Right(async move { handle.await? })
218228
}
@@ -247,13 +257,13 @@ impl TlsKeyLookup {
247257
}
248258

249259
/// Resolve a previously polled item.
250-
pub fn resolve(&self, sni: String, res: Result<TlsKey, AnyError>) {
260+
pub fn resolve(&self, sni: String, res: Result<TlsKey, String>) {
251261
_ = self
252262
.pending
253263
.borrow_mut()
254264
.remove(&sni)
255265
.unwrap()
256-
.send(res.map_err(Rc::new));
266+
.send(res.map_err(|e| Arc::new(e.into_boxed_str())));
257267
}
258268
}
259269

ext/websocket/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ pub fn create_ws_client_config(
349349
TlsKeys::Null,
350350
socket_use,
351351
)
352+
.map_err(|e| e.into())
352353
}
353354

354355
/// Headers common to both http/1.1 and h2 requests.

runtime/errors.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use deno_core::serde_json;
1717
use deno_core::url;
1818
use deno_core::ModuleResolutionError;
1919
use deno_cron::CronError;
20+
use deno_tls::TlsError;
2021
use std::env;
2122
use std::error::Error;
2223
use std::io;
@@ -157,6 +158,17 @@ pub fn get_nix_error_class(error: &nix::Error) -> &'static str {
157158
}
158159
}
159160

161+
fn get_tls_error_class(e: &TlsError) -> &'static str {
162+
match e {
163+
TlsError::Rustls(_) => "Error",
164+
TlsError::UnableAddPemFileToCert(e) => get_io_error_class(e),
165+
TlsError::CertInvalid
166+
| TlsError::CertsNotFound
167+
| TlsError::KeysNotFound
168+
| TlsError::KeyDecode => "InvalidData",
169+
}
170+
}
171+
160172
pub fn get_cron_error_class(e: &CronError) -> &'static str {
161173
match e {
162174
CronError::Resource(e) => {
@@ -211,6 +223,7 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
211223
.or_else(|| deno_web::get_error_class_name(e))
212224
.or_else(|| deno_webstorage::get_not_supported_error_class_name(e))
213225
.or_else(|| deno_websocket::get_network_error_class_name(e))
226+
.or_else(|| e.downcast_ref::<TlsError>().map(get_tls_error_class))
214227
.or_else(|| e.downcast_ref::<CronError>().map(get_cron_error_class))
215228
.or_else(|| e.downcast_ref::<CanvasError>().map(get_canvas_error))
216229
.or_else(|| e.downcast_ref::<CacheError>().map(get_cache_error))

0 commit comments

Comments
 (0)