wreq-rb 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +1922 -397
  3. data/LICENSE +203 -0
  4. data/README.md +19 -15
  5. data/ext/wreq_rb/Cargo.toml +4 -6
  6. data/ext/wreq_rb/src/client.rs +41 -48
  7. data/lib/wreq-rb/version.rb +1 -1
  8. data/patches/0001-add-transfer-size-tracking.patch +76 -67
  9. data/vendor/wreq/Cargo.toml +119 -71
  10. data/vendor/wreq/README.md +25 -20
  11. data/vendor/wreq/bench/http1.rs +25 -0
  12. data/vendor/wreq/bench/http1_over_tls.rs +25 -0
  13. data/vendor/wreq/bench/http2.rs +25 -0
  14. data/vendor/wreq/bench/http2_over_tls.rs +25 -0
  15. data/vendor/wreq/bench/support/bench.rs +91 -0
  16. data/vendor/wreq/bench/support/client.rs +217 -0
  17. data/vendor/wreq/bench/support/server.rs +188 -0
  18. data/vendor/wreq/bench/support.rs +56 -0
  19. data/vendor/wreq/examples/cert_store.rs +4 -4
  20. data/vendor/wreq/examples/{emulation.rs → emulate.rs} +2 -2
  21. data/vendor/wreq/examples/http2_websocket.rs +2 -2
  22. data/vendor/wreq/examples/keylog.rs +3 -3
  23. data/vendor/wreq/examples/{request_with_emulation.rs → request_with_emulate.rs} +2 -2
  24. data/vendor/wreq/examples/rt.rs +23 -0
  25. data/vendor/wreq/src/client/body.rs +23 -61
  26. data/vendor/wreq/src/client/emulate.rs +119 -0
  27. data/vendor/wreq/src/client/{http/future.rs → future.rs} +11 -32
  28. data/vendor/wreq/src/client/{http → layer}/client/pool.rs +66 -61
  29. data/vendor/wreq/src/client/{http → layer}/client.rs +416 -270
  30. data/vendor/wreq/src/client/layer/config.rs +27 -6
  31. data/vendor/wreq/src/client/layer/decoder.rs +9 -4
  32. data/vendor/wreq/src/client/layer/redirect/future.rs +6 -3
  33. data/vendor/wreq/src/client/layer/redirect.rs +4 -5
  34. data/vendor/wreq/src/client/layer/retry.rs +8 -5
  35. data/vendor/wreq/src/client/layer/timeout/body.rs +15 -6
  36. data/vendor/wreq/src/client/layer/timeout/future.rs +23 -18
  37. data/vendor/wreq/src/client/layer/timeout.rs +24 -74
  38. data/vendor/wreq/src/client/layer.rs +1 -2
  39. data/vendor/wreq/src/client/multipart.rs +137 -154
  40. data/vendor/wreq/src/client/request.rs +202 -118
  41. data/vendor/wreq/src/client/response.rs +46 -45
  42. data/vendor/wreq/src/client/upgrade.rs +15 -0
  43. data/vendor/wreq/src/client/ws.rs +73 -25
  44. data/vendor/wreq/src/client.rs +1655 -17
  45. data/vendor/wreq/src/config.rs +11 -11
  46. data/vendor/wreq/src/{client/conn → conn}/connector.rs +139 -137
  47. data/vendor/wreq/src/conn/descriptor.rs +143 -0
  48. data/vendor/wreq/src/conn/http.rs +484 -0
  49. data/vendor/wreq/src/conn/net/io.rs +75 -0
  50. data/vendor/wreq/src/conn/net/tcp/compio.rs +71 -0
  51. data/vendor/wreq/src/conn/net/tcp/tokio.rs +57 -0
  52. data/vendor/wreq/src/conn/net/tcp.rs +561 -0
  53. data/vendor/wreq/src/conn/net/uds/compio.rs +60 -0
  54. data/vendor/wreq/src/{client/conn/uds.rs → conn/net/uds/tokio.rs} +18 -12
  55. data/vendor/wreq/src/conn/net/uds.rs +11 -0
  56. data/vendor/wreq/src/conn/net.rs +130 -0
  57. data/vendor/wreq/src/{client/conn → conn}/proxy/socks.rs +2 -9
  58. data/vendor/wreq/src/{client/conn → conn}/proxy/tunnel.rs +21 -56
  59. data/vendor/wreq/src/conn/tls_info.rs +47 -0
  60. data/vendor/wreq/src/{client/conn.rs → conn.rs} +202 -54
  61. data/vendor/wreq/src/cookie.rs +302 -142
  62. data/vendor/wreq/src/dns/gai/compio.rs +77 -0
  63. data/vendor/wreq/src/dns/gai/tokio.rs +90 -0
  64. data/vendor/wreq/src/dns/gai.rs +14 -164
  65. data/vendor/wreq/src/dns/hickory.rs +16 -23
  66. data/vendor/wreq/src/dns/resolve.rs +7 -41
  67. data/vendor/wreq/src/dns.rs +90 -7
  68. data/vendor/wreq/src/error.rs +57 -31
  69. data/vendor/wreq/src/ext.rs +25 -0
  70. data/vendor/wreq/src/group.rs +211 -0
  71. data/vendor/wreq/src/header.rs +100 -112
  72. data/vendor/wreq/src/lib.rs +124 -73
  73. data/vendor/wreq/src/proxy.rs +6 -20
  74. data/vendor/wreq/src/redirect.rs +1 -1
  75. data/vendor/wreq/src/rt.rs +208 -0
  76. data/vendor/wreq/src/sync.rs +97 -98
  77. data/vendor/wreq/src/tls/compress.rs +124 -0
  78. data/vendor/wreq/src/tls/conn/ext.rs +54 -45
  79. data/vendor/wreq/src/tls/conn/service.rs +14 -18
  80. data/vendor/wreq/src/tls/conn.rs +169 -241
  81. data/vendor/wreq/src/tls/keylog.rs +68 -5
  82. data/vendor/wreq/src/tls/session.rs +205 -0
  83. data/vendor/wreq/src/tls/{x509 → trust}/identity.rs +4 -21
  84. data/vendor/wreq/src/tls/{x509/parser.rs → trust/parse.rs} +1 -1
  85. data/vendor/wreq/src/tls/{x509 → trust}/store.rs +42 -81
  86. data/vendor/wreq/src/tls/{x509.rs → trust.rs} +8 -2
  87. data/vendor/wreq/src/tls.rs +489 -25
  88. data/vendor/wreq/src/trace.rs +0 -12
  89. data/vendor/wreq/src/util.rs +1 -1
  90. data/vendor/wreq/tests/badssl.rs +10 -10
  91. data/vendor/wreq/tests/client.rs +3 -9
  92. data/vendor/wreq/tests/cookie.rs +6 -8
  93. data/vendor/wreq/tests/{emulation.rs → emulate.rs} +130 -22
  94. data/vendor/wreq/tests/multipart.rs +43 -1
  95. data/vendor/wreq/tests/proxy.rs +1 -1
  96. data/vendor/wreq/tests/support/layer.rs +1 -0
  97. metadata +49 -71
  98. data/patches/0002-add-cancel-connections.patch +0 -181
  99. data/vendor/wreq/src/client/conn/conn.rs +0 -231
  100. data/vendor/wreq/src/client/conn/http.rs +0 -1023
  101. data/vendor/wreq/src/client/conn/tls_info.rs +0 -98
  102. data/vendor/wreq/src/client/core/body/incoming.rs +0 -485
  103. data/vendor/wreq/src/client/core/body/length.rs +0 -118
  104. data/vendor/wreq/src/client/core/body.rs +0 -34
  105. data/vendor/wreq/src/client/core/common/buf.rs +0 -149
  106. data/vendor/wreq/src/client/core/common/rewind.rs +0 -141
  107. data/vendor/wreq/src/client/core/common/watch.rs +0 -76
  108. data/vendor/wreq/src/client/core/common.rs +0 -3
  109. data/vendor/wreq/src/client/core/conn/http1.rs +0 -342
  110. data/vendor/wreq/src/client/core/conn/http2.rs +0 -307
  111. data/vendor/wreq/src/client/core/conn.rs +0 -11
  112. data/vendor/wreq/src/client/core/dispatch.rs +0 -299
  113. data/vendor/wreq/src/client/core/error.rs +0 -435
  114. data/vendor/wreq/src/client/core/ext.rs +0 -201
  115. data/vendor/wreq/src/client/core/http1.rs +0 -178
  116. data/vendor/wreq/src/client/core/http2.rs +0 -483
  117. data/vendor/wreq/src/client/core/proto/h1/conn.rs +0 -988
  118. data/vendor/wreq/src/client/core/proto/h1/decode.rs +0 -1170
  119. data/vendor/wreq/src/client/core/proto/h1/dispatch.rs +0 -684
  120. data/vendor/wreq/src/client/core/proto/h1/encode.rs +0 -580
  121. data/vendor/wreq/src/client/core/proto/h1/io.rs +0 -879
  122. data/vendor/wreq/src/client/core/proto/h1/role.rs +0 -694
  123. data/vendor/wreq/src/client/core/proto/h1.rs +0 -104
  124. data/vendor/wreq/src/client/core/proto/h2/client.rs +0 -650
  125. data/vendor/wreq/src/client/core/proto/h2/ping.rs +0 -539
  126. data/vendor/wreq/src/client/core/proto/h2.rs +0 -379
  127. data/vendor/wreq/src/client/core/proto/headers.rs +0 -138
  128. data/vendor/wreq/src/client/core/proto.rs +0 -58
  129. data/vendor/wreq/src/client/core/rt/bounds.rs +0 -57
  130. data/vendor/wreq/src/client/core/rt/timer.rs +0 -150
  131. data/vendor/wreq/src/client/core/rt/tokio.rs +0 -99
  132. data/vendor/wreq/src/client/core/rt.rs +0 -25
  133. data/vendor/wreq/src/client/core/upgrade.rs +0 -267
  134. data/vendor/wreq/src/client/core.rs +0 -16
  135. data/vendor/wreq/src/client/emulation.rs +0 -161
  136. data/vendor/wreq/src/client/http/client/error.rs +0 -142
  137. data/vendor/wreq/src/client/http/client/exec.rs +0 -29
  138. data/vendor/wreq/src/client/http/client/extra.rs +0 -77
  139. data/vendor/wreq/src/client/http/client/util.rs +0 -104
  140. data/vendor/wreq/src/client/http.rs +0 -1629
  141. data/vendor/wreq/src/client/layer/config/options.rs +0 -156
  142. data/vendor/wreq/src/client/layer/cookie.rs +0 -161
  143. data/vendor/wreq/src/hash.rs +0 -143
  144. data/vendor/wreq/src/tls/conn/cache.rs +0 -123
  145. data/vendor/wreq/src/tls/conn/cert_compression.rs +0 -125
  146. data/vendor/wreq/src/tls/keylog/handle.rs +0 -64
  147. data/vendor/wreq/src/tls/options.rs +0 -464
  148. /data/vendor/wreq/src/client/{http → layer}/client/lazy.rs +0 -0
  149. /data/vendor/wreq/src/{client/conn → conn}/proxy.rs +0 -0
  150. /data/vendor/wreq/src/{client/conn → conn}/verbose.rs +0 -0
@@ -6,10 +6,6 @@
6
6
  //! The [`KeyLog`] enum lets you control key log behavior, either by respecting the
7
7
  //! `SSLKEYLOGFILE` environment variable or by specifying a custom file path. Handles are cached
8
8
  //! globally to avoid duplicate file access.
9
- //!
10
- //! Use [`KeyLog::handle`] to obtain a [`Handle`] for writing keys.
11
-
12
- mod handle;
13
9
 
14
10
  use std::{
15
11
  borrow::Cow,
@@ -51,7 +47,7 @@ impl KeyLog {
51
47
  .0
52
48
  .ok_or_else(|| Error::new(ErrorKind::NotFound, "KeyLog: file path is not specified"))?;
53
49
 
54
- let cache = GLOBAL_KEYLOG_CACHE.get_or_init(Default::default);
50
+ let cache = GLOBAL_KEYLOG_CACHE.get_or_init(RwLock::default);
55
51
  if let Some(handle) = cache.read().get(path.as_ref()).cloned() {
56
52
  return Ok(handle);
57
53
  }
@@ -97,3 +93,70 @@ where
97
93
  }
98
94
  ret
99
95
  }
96
+
97
+ mod handle {
98
+ use std::{
99
+ fs::OpenOptions,
100
+ io::{Result, Write},
101
+ path::Path,
102
+ sync::{
103
+ Arc,
104
+ mpsc::{self, Sender},
105
+ },
106
+ };
107
+
108
+ /// Handle for writing to a key log file.
109
+ #[derive(Debug, Clone)]
110
+ pub struct Handle {
111
+ #[allow(unused)]
112
+ filepath: Arc<Path>,
113
+ sender: Sender<String>,
114
+ }
115
+
116
+ impl Handle {
117
+ /// Create a new [`Handle`] with the specified path and sender.
118
+ pub fn new(filepath: Arc<Path>) -> Result<Self> {
119
+ if let Some(parent) = filepath.parent() {
120
+ std::fs::create_dir_all(parent)?;
121
+ }
122
+
123
+ let mut file = OpenOptions::new()
124
+ .create(true)
125
+ .append(true)
126
+ .open(&filepath)?;
127
+
128
+ let (sender, receiver) = mpsc::channel::<String>();
129
+
130
+ let _path_name = filepath.clone();
131
+ std::thread::spawn(move || {
132
+ trace!(
133
+ file = ?_path_name,
134
+ "Handle: receiver task up and running",
135
+ );
136
+ while let Ok(line) = receiver.recv() {
137
+ if let Err(_err) = file.write_all(line.as_bytes()) {
138
+ error!(
139
+ file = ?_path_name,
140
+ error = %_err,
141
+ "Handle: failed to write file",
142
+ );
143
+ }
144
+ }
145
+ });
146
+
147
+ Ok(Handle { filepath, sender })
148
+ }
149
+
150
+ /// Write a line to the keylogger.
151
+ pub fn write(&self, line: &str) {
152
+ let line = format!("{line}\n");
153
+ if let Err(_err) = self.sender.send(line) {
154
+ error!(
155
+ file = ?self.filepath,
156
+ error = %_err,
157
+ "Handle: failed to send log line for writing",
158
+ );
159
+ }
160
+ }
161
+ }
162
+ }
@@ -0,0 +1,205 @@
1
+ //! TLS session caching and resumption.
2
+ //!
3
+ //! Handshakes are expensive. This module lets you reuse sessions to save
4
+ //! CPU cycles and reduce latency.
5
+ //!
6
+ //! By default, we use an in-memory LRU cache, but you can plug in your own
7
+ //! implementation if you're running at scale or need to share sessions
8
+ //! across multiple instances.
9
+
10
+ use std::{
11
+ borrow::Borrow,
12
+ collections::{HashMap, hash_map::Entry},
13
+ hash::{Hash, Hasher},
14
+ num::NonZeroUsize,
15
+ sync::Arc,
16
+ };
17
+
18
+ use btls::ssl::{SslSession, SslVersion};
19
+ use lru::LruCache;
20
+
21
+ use crate::{conn::descriptor::ConnectionId, sync::Mutex, tls::TlsVersion};
22
+
23
+ /// An opaque key identifying a TLS session cache entry.
24
+ #[derive(Clone, PartialEq, Eq, Hash)]
25
+ pub struct Key(pub(super) ConnectionId);
26
+
27
+ /// A TLS session that can be stored and retrieved from a session cache.
28
+ #[derive(Clone)]
29
+ pub struct TlsSession(pub(super) SslSession);
30
+
31
+ /// A trait for cache storing and retrieving TLS sessions.
32
+ ///
33
+ /// # TLS 1.3 Session Handling
34
+ ///
35
+ /// For TLS 1.3 sessions, implementations **should** remove the session after
36
+ /// retrieval to comply with [RFC 8446 Appendix C.4](https://tools.ietf.org/html/rfc8446#appendix-C.4),
37
+ /// which requires that session tickets are used at most once to prevent
38
+ /// concurrent handshakes from reusing the same session.
39
+ pub trait TlsSessionCache: Send + Sync {
40
+ /// Store a TLS session associated with the given key.
41
+ fn put(&self, key: Key, session: TlsSession);
42
+
43
+ /// Retrieve a TLS session for the given key.
44
+ ///
45
+ /// For TLS 1.3, the session should be removed from the cache upon retrieval
46
+ /// to ensure single-use semantics (see [RFC 8446 Appendix C.4]).
47
+ fn pop(&self, key: &Key) -> Option<TlsSession>;
48
+ }
49
+
50
+ impl_into_shared!(
51
+ /// Trait for converting types into a shared [`TlsSessionCache`].
52
+ ///
53
+ /// This allows accepting bare types, `Arc<T>`, or `Arc<dyn TlsSessionCache>`.
54
+ pub trait IntoTlsSessionCache => TlsSessionCache
55
+ );
56
+
57
+ /// The default two-level LRU session cache.
58
+ ///
59
+ /// Maintains both forward (key → sessions) and reverse (session → key) lookups
60
+ /// for efficient session storage, retrieval, and cleanup operations.
61
+ ///
62
+ /// This is the built-in implementation of [`TlsSessionCache`] used when no
63
+ /// custom session store is configured.
64
+ pub struct LruTlsSessionCache {
65
+ inner: Mutex<Inner>,
66
+ per_host_session_capacity: usize,
67
+ }
68
+
69
+ struct Inner {
70
+ reverse: HashMap<TlsSession, Key>,
71
+ per_host_sessions: HashMap<Key, LruCache<TlsSession, ()>>,
72
+ }
73
+
74
+ // ===== impl TlsSession =====
75
+
76
+ impl TlsSession {
77
+ /// Returns the TLS session ID.
78
+ #[inline]
79
+ pub fn id(&self) -> &[u8] {
80
+ self.0.id()
81
+ }
82
+
83
+ /// Returns the time at which the session was established, in seconds since the Unix epoch.
84
+ #[inline]
85
+ pub fn time(&self) -> u64 {
86
+ self.0.time()
87
+ }
88
+
89
+ /// Returns the sessions timeout, in seconds.
90
+ ///
91
+ /// A session older than this time should not be used for session resumption.
92
+ #[inline]
93
+ pub fn timeout(&self) -> u32 {
94
+ self.0.timeout()
95
+ }
96
+
97
+ /// Returns the TLS protocol version negotiated for this session.
98
+ #[inline]
99
+ pub fn protocol_version(&self) -> TlsVersion {
100
+ let version = self.0.protocol_version();
101
+ if version == SslVersion::SSL3 {
102
+ // SSLv3 (SSL 3.0) is obsolete and insecure, and is not supported by btls.
103
+ // This branch should never be reached in normal operation. If it is,
104
+ // it indicates a bug or an unsupported/legacy OpenSSL configuration.
105
+ unreachable!(
106
+ "Encountered unsupported protocol: SSLv3 (SSL 3.0) is obsolete and not accepted by btls"
107
+ );
108
+ }
109
+ TlsVersion(version)
110
+ }
111
+ }
112
+
113
+ impl Eq for TlsSession {}
114
+
115
+ impl PartialEq for TlsSession {
116
+ #[inline]
117
+ fn eq(&self, other: &TlsSession) -> bool {
118
+ self.0.id() == other.0.id()
119
+ }
120
+ }
121
+
122
+ impl Hash for TlsSession {
123
+ #[inline]
124
+ fn hash<H: Hasher>(&self, state: &mut H) {
125
+ self.0.id().hash(state);
126
+ }
127
+ }
128
+
129
+ impl Borrow<[u8]> for TlsSession {
130
+ #[inline]
131
+ fn borrow(&self) -> &[u8] {
132
+ self.0.id()
133
+ }
134
+ }
135
+
136
+ // ===== impl LruTlsSessionCache =====
137
+
138
+ impl LruTlsSessionCache {
139
+ /// Creates a new [`LruTlsSessionCache`] with the given per-host capacity.
140
+ pub fn new(per_host_session_capacity: usize) -> Self {
141
+ LruTlsSessionCache {
142
+ inner: Mutex::new(Inner {
143
+ reverse: HashMap::new(),
144
+ per_host_sessions: HashMap::new(),
145
+ }),
146
+ per_host_session_capacity,
147
+ }
148
+ }
149
+ }
150
+
151
+ impl TlsSessionCache for LruTlsSessionCache {
152
+ fn put(&self, key: Key, session: TlsSession) {
153
+ let mut inner = self.inner.lock();
154
+
155
+ let evicted = {
156
+ let per_host_sessions =
157
+ inner
158
+ .per_host_sessions
159
+ .entry(key.clone())
160
+ .or_insert_with(|| {
161
+ NonZeroUsize::new(self.per_host_session_capacity)
162
+ .map_or_else(LruCache::unbounded, LruCache::new)
163
+ });
164
+
165
+ // Enforce per-key capacity limit by evicting the least recently used session
166
+ let evicted = if per_host_sessions.len() >= self.per_host_session_capacity {
167
+ per_host_sessions.pop_lru().map(|(s, _)| s)
168
+ } else {
169
+ None
170
+ };
171
+
172
+ per_host_sessions.put(session.clone(), ());
173
+ evicted
174
+ };
175
+
176
+ if let Some(evicted_session) = evicted {
177
+ inner.reverse.remove(&evicted_session);
178
+ }
179
+ inner.reverse.insert(session, key);
180
+ }
181
+
182
+ fn pop(&self, key: &Key) -> Option<TlsSession> {
183
+ let mut inner = self.inner.lock();
184
+ let session = {
185
+ let per_host_sessions = inner.per_host_sessions.get_mut(key)?;
186
+ per_host_sessions.peek_lru()?.0.clone()
187
+ };
188
+
189
+ // https://tools.ietf.org/html/rfc8446#appendix-C.4
190
+ // OpenSSL will remove the session from its cache after the handshake completes anyway, but
191
+ // this ensures that concurrent handshakes don't end up with the same session.
192
+ if session.protocol_version() == TlsVersion::TLS_1_3 {
193
+ if let Some(key) = inner.reverse.remove(&session) {
194
+ if let Entry::Occupied(mut entry) = inner.per_host_sessions.entry(key) {
195
+ entry.get_mut().pop(&session);
196
+ if entry.get().is_empty() {
197
+ entry.remove();
198
+ }
199
+ }
200
+ }
201
+ }
202
+
203
+ Some(session)
204
+ }
205
+ }
@@ -1,4 +1,4 @@
1
- use boring2::{
1
+ use btls::{
2
2
  pkcs12::Pkcs12,
3
3
  pkey::{PKey, Private},
4
4
  x509::X509,
@@ -9,9 +9,9 @@ use crate::Error;
9
9
  /// Represents a private key and X509 cert as a client certificate.
10
10
  #[derive(Debug, Clone)]
11
11
  pub struct Identity {
12
- pkey: PKey<Private>,
13
- cert: X509,
14
- chain: Vec<X509>,
12
+ pub(in crate::tls) pkey: PKey<Private>,
13
+ pub(in crate::tls) cert: X509,
14
+ pub(in crate::tls) chain: Vec<X509>,
15
15
  }
16
16
 
17
17
  impl Identity {
@@ -87,23 +87,6 @@ impl Identity {
87
87
  let chain = cert_chain.collect();
88
88
  Ok(Identity { pkey, cert, chain })
89
89
  }
90
-
91
- pub(crate) fn add_to_tls(
92
- &self,
93
- connector: &mut boring2::ssl::SslConnectorBuilder,
94
- ) -> crate::Result<()> {
95
- connector.set_certificate(&self.cert).map_err(Error::tls)?;
96
- connector.set_private_key(&self.pkey).map_err(Error::tls)?;
97
- for cert in self.chain.iter() {
98
- // https://www.openssl.org/docs/manmaster/man3/SSL_CTX_add_extra_chain_cert.html
99
- // specifies that "When sending a certificate chain, extra chain certificates are
100
- // sent in order following the end entity certificate."
101
- connector
102
- .add_extra_chain_cert(cert.clone())
103
- .map_err(Error::tls)?;
104
- }
105
- Ok(())
106
- }
107
90
  }
108
91
 
109
92
  #[cfg(test)]
@@ -1,4 +1,4 @@
1
- use boring2::x509::store::{X509Store, X509StoreBuilder};
1
+ use btls::x509::store::{X509Store, X509StoreBuilder};
2
2
 
3
3
  use super::{Certificate, CertificateInput};
4
4
  use crate::{Error, Result};
@@ -1,24 +1,51 @@
1
1
  use std::sync::Arc;
2
2
 
3
- use boring2::{
4
- ssl::SslConnectorBuilder,
5
- x509::store::{X509Store, X509StoreBuilder},
6
- };
3
+ use btls::x509::store::{X509Store, X509StoreBuilder};
7
4
 
8
5
  use super::{
9
6
  Certificate, CertificateInput,
10
- parser::{filter_map_certs, parse_certs, parse_certs_with_stack, process_certs},
7
+ parse::{filter_map_certs, parse_certs, parse_certs_with_stack, process_certs},
11
8
  };
12
9
  use crate::{Error, Result};
13
10
 
14
- /// A builder for constructing a `CertStore`.
11
+ /// A builder for constructing a [`CertStore`].
15
12
  pub struct CertStoreBuilder {
16
13
  builder: Result<X509StoreBuilder>,
17
14
  }
18
15
 
19
- // ====== impl CertStoreBuilder ======
20
-
21
16
  impl CertStoreBuilder {
17
+ fn parse_cert<'c, C, P>(mut self, cert: C, parser: P) -> Self
18
+ where
19
+ C: Into<CertificateInput<'c>>,
20
+ P: Fn(&'c [u8]) -> Result<Certificate>,
21
+ {
22
+ if let Ok(ref mut builder) = self.builder {
23
+ let input = cert.into();
24
+ let result = input
25
+ .with_parser(parser)
26
+ .and_then(|cert| builder.add_cert(cert.0).map_err(Error::tls));
27
+
28
+ if let Err(err) = result {
29
+ self.builder = Err(err);
30
+ }
31
+ }
32
+ self
33
+ }
34
+
35
+ fn parse_certs<'c, I>(mut self, certs: I, parser: fn(&'c [u8]) -> Result<Certificate>) -> Self
36
+ where
37
+ I: IntoIterator,
38
+ I::Item: Into<CertificateInput<'c>>,
39
+ {
40
+ if let Ok(ref mut builder) = self.builder {
41
+ let certs = filter_map_certs(certs, parser);
42
+ if let Err(err) = process_certs(certs, builder) {
43
+ self.builder = Err(err);
44
+ }
45
+ }
46
+ self
47
+ }
48
+
22
49
  /// Adds a DER-encoded certificate to the certificate store.
23
50
  #[inline]
24
51
  pub fn add_der_cert<'c, C>(self, cert: C) -> Self
@@ -87,9 +114,9 @@ impl CertStoreBuilder {
87
114
  self
88
115
  }
89
116
 
90
- /// Constructs the `CertStore`.
117
+ /// Constructs the [`CertStore`].
91
118
  ///
92
- /// This method finalizes the builder and constructs the `CertStore`
119
+ /// This method finalizes the builder and constructs the [`CertStore`]
93
120
  /// containing all the added certificates.
94
121
  #[inline]
95
122
  pub fn build(self) -> Result<CertStore> {
@@ -100,40 +127,6 @@ impl CertStoreBuilder {
100
127
  }
101
128
  }
102
129
 
103
- impl CertStoreBuilder {
104
- fn parse_cert<'c, C, P>(mut self, cert: C, parser: P) -> Self
105
- where
106
- C: Into<CertificateInput<'c>>,
107
- P: Fn(&'c [u8]) -> Result<Certificate>,
108
- {
109
- if let Ok(ref mut builder) = self.builder {
110
- let input = cert.into();
111
- let result = input
112
- .with_parser(parser)
113
- .and_then(|cert| builder.add_cert(cert.0).map_err(Error::tls));
114
-
115
- if let Err(err) = result {
116
- self.builder = Err(err);
117
- }
118
- }
119
- self
120
- }
121
-
122
- fn parse_certs<'c, I>(mut self, certs: I, parser: fn(&'c [u8]) -> Result<Certificate>) -> Self
123
- where
124
- I: IntoIterator,
125
- I::Item: Into<CertificateInput<'c>>,
126
- {
127
- if let Ok(ref mut builder) = self.builder {
128
- let certs = filter_map_certs(certs, parser);
129
- if let Err(err) = process_certs(certs, builder) {
130
- self.builder = Err(err);
131
- }
132
- }
133
- self
134
- }
135
- }
136
-
137
130
  /// A thread-safe certificate store for TLS connections.
138
131
  ///
139
132
  /// [`CertStore`] manages a collection of trusted certificates used for verifying peer identities.
@@ -148,12 +141,10 @@ impl CertStoreBuilder {
148
141
  /// [`Rc`]: std::rc::Rc
149
142
  /// [`Arc`]: std::sync::Arc
150
143
  #[derive(Clone)]
151
- pub struct CertStore(Arc<X509Store>);
152
-
153
- // ====== impl CertStore ======
144
+ pub struct CertStore(pub(in crate::tls) Arc<X509Store>);
154
145
 
155
146
  impl CertStore {
156
- /// Creates a new `CertStoreBuilder`.
147
+ /// Creates a new [`CertStoreBuilder`].
157
148
  #[inline]
158
149
  pub fn builder() -> CertStoreBuilder {
159
150
  CertStoreBuilder {
@@ -161,7 +152,7 @@ impl CertStore {
161
152
  }
162
153
  }
163
154
 
164
- /// Creates a new `CertStore` from a collection of DER-encoded certificates.
155
+ /// Creates a new [`CertStore`] from a collection of DER-encoded certificates.
165
156
  #[inline]
166
157
  pub fn from_der_certs<'c, C>(certs: C) -> Result<CertStore>
167
158
  where
@@ -173,7 +164,7 @@ impl CertStore {
173
164
  .map(CertStore)
174
165
  }
175
166
 
176
- /// Creates a new `CertStore` from a collection of PEM-encoded certificates.
167
+ /// Creates a new [`CertStore`] from a collection of PEM-encoded certificates.
177
168
  #[inline]
178
169
  pub fn from_pem_certs<'c, C>(certs: C) -> Result<CertStore>
179
170
  where
@@ -185,7 +176,7 @@ impl CertStore {
185
176
  .map(CertStore)
186
177
  }
187
178
 
188
- /// Creates a new `CertStore` from a PEM-encoded certificate stack.
179
+ /// Creates a new [`CertStore`] from a PEM-encoded certificate stack.
189
180
  #[inline]
190
181
  pub fn from_pem_stack<C>(certs: C) -> Result<CertStore>
191
182
  where
@@ -196,33 +187,3 @@ impl CertStore {
196
187
  .map(CertStore)
197
188
  }
198
189
  }
199
-
200
- impl CertStore {
201
- #[inline]
202
- pub(crate) fn add_to_tls(&self, tls: &mut SslConnectorBuilder) {
203
- tls.set_cert_store_ref(&self.0);
204
- }
205
- }
206
-
207
- impl Default for CertStore {
208
- fn default() -> Self {
209
- #[cfg(feature = "webpki-roots")]
210
- static LOAD_CERTS: std::sync::LazyLock<CertStore> = std::sync::LazyLock::new(|| {
211
- CertStore::builder()
212
- .add_der_certs(webpki_root_certs::TLS_SERVER_ROOT_CERTS)
213
- .build()
214
- .expect("failed to load default cert store")
215
- });
216
-
217
- #[cfg(not(feature = "webpki-roots"))]
218
- {
219
- CertStore::builder()
220
- .set_default_paths()
221
- .build()
222
- .expect("failed to load default cert store")
223
- }
224
-
225
- #[cfg(feature = "webpki-roots")]
226
- LOAD_CERTS.clone()
227
- }
228
- }
@@ -1,8 +1,14 @@
1
+ //! TLS Trust and Identity management.
2
+ //!
3
+ //! Handles server certificate verification, mTLS identity, and CA
4
+ //! bundle management. Provides DER/PEM parsing for BoringSSL and
5
+ //! supports both system and custom trust stores.
6
+
1
7
  mod identity;
2
- mod parser;
8
+ mod parse;
3
9
  mod store;
4
10
 
5
- use boring2::x509::X509;
11
+ use btls::x509::X509;
6
12
 
7
13
  pub use self::{
8
14
  identity::Identity,