1use crate::{
5 certificate::{Format, IntoCertificate, IntoPrivateKey},
6 keylog::KeyLogHandle,
7 params::Params,
8 session::Session,
9 ConfigLoader,
10};
11use s2n_codec::EncoderValue;
12use s2n_quic_core::{application::ServerName, crypto::tls, endpoint};
13#[cfg(any(test, feature = "unstable_client_hello"))]
14use s2n_tls::callbacks::ClientHelloCallback;
15#[cfg(any(test, feature = "unstable_private_key"))]
16use s2n_tls::callbacks::PrivateKeyCallback;
17use s2n_tls::{
18 callbacks::VerifyHostNameCallback,
19 config::{self, Config},
20 enums::ClientAuthType,
21 error::Error,
22};
23use std::sync::Arc;
24
25pub struct Server<L: ConfigLoader = Config> {
26 loader: L,
27 #[allow(dead_code)] keylog: Option<KeyLogHandle>,
29 params: Params,
30}
31
32impl Server {
33 pub fn builder() -> Builder {
34 Builder::default()
35 }
36}
37
38impl<L: ConfigLoader> Server<L> {
39 pub fn from_loader(loader: L) -> Self {
47 Self {
48 loader,
49 keylog: None,
50 params: Default::default(),
51 }
52 }
53}
54
55impl Default for Server {
56 fn default() -> Self {
57 Self::builder()
58 .build()
59 .expect("could not create a default server")
60 }
61}
62
63impl<L: ConfigLoader> ConfigLoader for Server<L> {
64 #[inline]
65 fn load(&mut self, cx: crate::ConnectionContext) -> s2n_tls::config::Config {
66 self.loader.load(cx)
67 }
68}
69
70impl<L: ConfigLoader> From<Server<L>> for Config {
71 fn from(mut server: Server<L>) -> Self {
72 server.load(crate::ConnectionContext { server_name: None })
73 }
74}
75
76pub struct Builder {
77 config: config::Builder,
78 keylog: Option<KeyLogHandle>,
79}
80
81impl Default for Builder {
82 fn default() -> Self {
83 let mut config = config::Builder::default();
84 config.enable_quic().unwrap();
85 config.set_security_policy(crate::DEFAULT_POLICY).unwrap();
87 config.set_application_protocol_preference([b"h3"]).unwrap();
88
89 Self {
90 config,
91 keylog: None,
92 }
93 }
94}
95
96impl Builder {
97 pub fn config_mut(&mut self) -> &mut s2n_tls::config::Builder {
98 &mut self.config
99 }
100
101 #[cfg(any(test, feature = "unstable_client_hello"))]
102 pub fn with_client_hello_handler<T: 'static + ClientHelloCallback>(
103 mut self,
104 handler: T,
105 ) -> Result<Self, Error> {
106 self.config.set_client_hello_callback(handler)?;
107 Ok(self)
108 }
109
110 #[cfg(any(test, feature = "unstable_private_key"))]
111 pub fn with_private_key_handler<T: 'static + PrivateKeyCallback>(
112 mut self,
113 handler: T,
114 ) -> Result<Self, Error> {
115 self.config.set_private_key_callback(handler)?;
116 Ok(self)
117 }
118
119 pub fn with_application_protocols<P: IntoIterator<Item = I>, I: AsRef<[u8]>>(
120 mut self,
121 protocols: P,
122 ) -> Result<Self, Error> {
123 self.config.set_application_protocol_preference(protocols)?;
124 Ok(self)
125 }
126
127 pub fn with_certificate<C: IntoCertificate, PK: IntoPrivateKey>(
128 mut self,
129 certificate: C,
130 private_key: PK,
131 ) -> Result<Self, Error> {
132 let private_key = private_key.into_private_key()?.0;
133 let certificate = certificate.into_certificate()?.0;
134 let certificate = certificate
135 .as_pem()
136 .expect("pem is currently the only certificate format supported");
137 match private_key {
138 Format::Pem(bytes) => self.config.load_pem(certificate, bytes.as_ref())?,
139 Format::None => self.config.load_public_pem(certificate)?,
140 Format::Der(_) => panic!("der private keys not supported"),
141 };
142 Ok(self)
143 }
144
145 pub fn with_trusted_certificate<C: IntoCertificate>(
146 mut self,
147 certificate: C,
148 ) -> Result<Self, Error> {
149 let certificate = certificate.into_certificate()?;
150 let certificate = certificate
151 .0
152 .as_pem()
153 .expect("pem is currently the only certificate format supported");
154 self.config.trust_pem(certificate)?;
155 Ok(self)
156 }
157
158 pub fn with_empty_trust_store(mut self) -> Result<Self, Error> {
168 self.config.wipe_trust_store()?;
169 Ok(self)
170 }
171
172 pub fn with_client_authentication(mut self) -> Result<Self, Error> {
174 self.config.set_client_auth_type(ClientAuthType::Required)?;
175 Ok(self)
176 }
177
178 #[deprecated(note = "use `with_verify_host_name_callback` instead")]
181 pub fn with_verify_client_certificate_handler<T: 'static + VerifyHostNameCallback>(
182 mut self,
183 handler: T,
184 ) -> Result<Self, Error> {
185 self.config.set_verify_host_callback(handler)?;
186 Ok(self)
187 }
188
189 pub fn with_verify_host_name_callback<T: 'static + VerifyHostNameCallback>(
194 mut self,
195 handler: T,
196 ) -> Result<Self, Error> {
197 self.config.set_verify_host_callback(handler)?;
198 Ok(self)
199 }
200
201 pub fn with_key_logging(mut self) -> Result<Self, Error> {
202 use crate::keylog::KeyLog;
203
204 self.keylog = KeyLog::try_open();
205
206 unsafe {
207 if let Some(keylog) = self.keylog.as_ref() {
209 self.config
210 .set_key_log_callback(Some(KeyLog::callback), Arc::as_ptr(keylog) as *mut _)?;
211 } else {
212 self.config
214 .set_key_log_callback(None, core::ptr::null_mut())?;
215 }
216 }
217
218 Ok(self)
219 }
220
221 pub fn build(self) -> Result<Server, Error> {
222 #[cfg(feature = "fips")]
223 assert!(s2n_tls::init::fips_mode()?.is_enabled());
224
225 Ok(Server {
226 loader: self.config.build()?,
227 keylog: self.keylog,
228 params: Default::default(),
229 })
230 }
231}
232
233impl<L: ConfigLoader> tls::Endpoint for Server<L> {
234 type Session = Session;
235
236 fn new_server_session<Params: EncoderValue>(&mut self, params: &Params) -> Self::Session {
237 let config = self
238 .loader
239 .load(crate::ConnectionContext { server_name: None });
240 self.params.with(params, |params| {
241 Session::new(endpoint::Type::Server, config, params, None).unwrap()
242 })
243 }
244
245 fn new_client_session<Params: EncoderValue>(
246 &mut self,
247 _transport_parameters: &Params,
248 _erver_name: ServerName,
249 ) -> Self::Session {
250 panic!("cannot create a client session from a server config");
251 }
252
253 fn max_tag_length(&self) -> usize {
254 s2n_quic_crypto::MAX_TAG_LEN
255 }
256}