use crate::builder::{ConfigBuilder, WantsCipherSuites};
use crate::common_state::{CommonState, Context, Side, State};
use crate::conn::{ConnectionCommon, ConnectionCore};
use crate::dns_name::DnsName;
use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme};
use crate::error::Error;
use crate::kx::SupportedKxGroup;
#[cfg(feature = "logging")]
use crate::log::trace;
use crate::msgs::base::Payload;
use crate::msgs::handshake::{ClientHelloPayload, ProtocolName, ServerExtension};
use crate::msgs::message::Message;
use crate::sign;
use crate::suites::SupportedCipherSuite;
use crate::vecbuf::ChunkVecBuffer;
use crate::verify;
#[cfg(feature = "secret_extraction")]
use crate::ExtractedSecrets;
use crate::KeyLog;
use super::hs;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use std::{fmt, io};
pub trait StoresServerSessions: Send + Sync {
fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool;
fn get(&self, key: &[u8]) -> Option<Vec<u8>>;
fn take(&self, key: &[u8]) -> Option<Vec<u8>>;
fn can_cache(&self) -> bool;
}
pub trait ProducesTickets: Send + Sync {
fn enabled(&self) -> bool;
fn lifetime(&self) -> u32;
fn encrypt(&self, plain: &[u8]) -> Option<Vec<u8>>;
fn decrypt(&self, cipher: &[u8]) -> Option<Vec<u8>>;
}
pub trait ResolvesServerCert: Send + Sync {
fn resolve(&self, client_hello: ClientHello) -> Option<Arc<sign::CertifiedKey>>;
}
pub struct ClientHello<'a> {
server_name: &'a Option<DnsName>,
signature_schemes: &'a [SignatureScheme],
alpn: Option<&'a Vec<ProtocolName>>,
cipher_suites: &'a [CipherSuite],
}
impl<'a> ClientHello<'a> {
pub(super) fn new(
server_name: &'a Option<DnsName>,
signature_schemes: &'a [SignatureScheme],
alpn: Option<&'a Vec<ProtocolName>>,
cipher_suites: &'a [CipherSuite],
) -> Self {
trace!("sni {:?}", server_name);
trace!("sig schemes {:?}", signature_schemes);
trace!("alpn protocols {:?}", alpn);
trace!("cipher suites {:?}", cipher_suites);
ClientHello {
server_name,
signature_schemes,
alpn,
cipher_suites,
}
}
pub fn server_name(&self) -> Option<&str> {
self.server_name
.as_ref()
.map(<DnsName as AsRef<str>>::as_ref)
}
pub fn signature_schemes(&self) -> &[SignatureScheme] {
self.signature_schemes
}
pub fn alpn(&self) -> Option<impl Iterator<Item = &'a [u8]>> {
self.alpn.map(|protocols| {
protocols
.iter()
.map(|proto| proto.as_ref())
})
}
pub fn cipher_suites(&self) -> &[CipherSuite] {
self.cipher_suites
}
}
#[derive(Clone)]
pub struct ServerConfig {
pub(super) cipher_suites: Vec<SupportedCipherSuite>,
pub(super) kx_groups: Vec<&'static SupportedKxGroup>,
pub ignore_client_order: bool,
pub max_fragment_size: Option<usize>,
pub session_storage: Arc<dyn StoresServerSessions + Send + Sync>,
pub ticketer: Arc<dyn ProducesTickets>,
pub cert_resolver: Arc<dyn ResolvesServerCert>,
pub alpn_protocols: Vec<Vec<u8>>,
pub(super) versions: crate::versions::EnabledVersions,
pub(super) verifier: Arc<dyn verify::ClientCertVerifier>,
pub key_log: Arc<dyn KeyLog>,
#[cfg(feature = "secret_extraction")]
#[cfg_attr(docsrs, doc(cfg(feature = "secret_extraction")))]
pub enable_secret_extraction: bool,
pub max_early_data_size: u32,
pub send_half_rtt_data: bool,
pub send_tls13_tickets: usize,
}
impl fmt::Debug for ServerConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ServerConfig")
.field("ignore_client_order", &self.ignore_client_order)
.field("max_fragment_size", &self.max_fragment_size)
.field("alpn_protocols", &self.alpn_protocols)
.field("max_early_data_size", &self.max_early_data_size)
.field("send_half_rtt_data", &self.send_half_rtt_data)
.field("send_tls13_tickets", &self.send_tls13_tickets)
.finish_non_exhaustive()
}
}
impl ServerConfig {
pub fn builder() -> ConfigBuilder<Self, WantsCipherSuites> {
ConfigBuilder {
state: WantsCipherSuites(()),
side: PhantomData,
}
}
pub(crate) fn supports_version(&self, v: ProtocolVersion) -> bool {
self.versions.contains(v)
&& self
.cipher_suites
.iter()
.any(|cs| cs.version().version == v)
}
}
pub struct ReadEarlyData<'a> {
early_data: &'a mut EarlyDataState,
}
impl<'a> ReadEarlyData<'a> {
fn new(early_data: &'a mut EarlyDataState) -> Self {
ReadEarlyData { early_data }
}
}
impl<'a> io::Read for ReadEarlyData<'a> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.early_data.read(buf)
}
#[cfg(read_buf)]
fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> {
self.early_data.read_buf(cursor)
}
}
pub struct ServerConnection {
inner: ConnectionCommon<ServerConnectionData>,
}
impl ServerConnection {
pub fn new(config: Arc<ServerConfig>) -> Result<Self, Error> {
Ok(Self {
inner: ConnectionCommon::from(ConnectionCore::for_server(config, Vec::new())?),
})
}
pub fn server_name(&self) -> Option<&str> {
self.inner.core.get_sni_str()
}
pub fn received_resumption_data(&self) -> Option<&[u8]> {
self.inner
.core
.data
.received_resumption_data
.as_ref()
.map(|x| &x[..])
}
pub fn set_resumption_data(&mut self, data: &[u8]) {
assert!(data.len() < 2usize.pow(15));
self.inner.core.data.resumption_data = data.into();
}
pub fn reject_early_data(&mut self) {
self.inner.core.reject_early_data()
}
pub fn early_data(&mut self) -> Option<ReadEarlyData> {
let data = &mut self.inner.core.data;
if data.early_data.was_accepted() {
Some(ReadEarlyData::new(&mut data.early_data))
} else {
None
}
}
#[cfg(feature = "secret_extraction")]
#[cfg_attr(docsrs, doc(cfg(feature = "secret_extraction")))]
pub fn extract_secrets(self) -> Result<ExtractedSecrets, Error> {
self.inner.extract_secrets()
}
}
impl fmt::Debug for ServerConnection {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("ServerConnection")
.finish()
}
}
impl Deref for ServerConnection {
type Target = ConnectionCommon<ServerConnectionData>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for ServerConnection {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl From<ServerConnection> for crate::Connection {
fn from(conn: ServerConnection) -> Self {
Self::Server(conn)
}
}
pub struct Acceptor {
inner: Option<ConnectionCommon<ServerConnectionData>>,
}
impl Default for Acceptor {
fn default() -> Self {
Self {
inner: Some(
ConnectionCore::new(
Box::new(Accepting),
ServerConnectionData::default(),
CommonState::new(Side::Server),
)
.into(),
),
}
}
}
impl Acceptor {
pub fn read_tls(&mut self, rd: &mut dyn io::Read) -> Result<usize, io::Error> {
match &mut self.inner {
Some(conn) => conn.read_tls(rd),
None => Err(io::Error::new(
io::ErrorKind::Other,
"acceptor cannot read after successful acceptance",
)),
}
}
pub fn accept(&mut self) -> Result<Option<Accepted>, Error> {
let mut connection = match self.inner.take() {
Some(conn) => conn,
None => {
return Err(Error::General("Acceptor polled after completion".into()));
}
};
let message = match connection.first_handshake_message()? {
Some(msg) => msg,
None => {
self.inner = Some(connection);
return Ok(None);
}
};
let (_, sig_schemes) =
hs::process_client_hello(&message, false, &mut Context::from(&mut connection))?;
Ok(Some(Accepted {
connection,
message,
sig_schemes,
}))
}
}
pub struct Accepted {
connection: ConnectionCommon<ServerConnectionData>,
message: Message,
sig_schemes: Vec<SignatureScheme>,
}
impl Accepted {
pub fn client_hello(&self) -> ClientHello<'_> {
let payload = Self::client_hello_payload(&self.message);
ClientHello::new(
&self.connection.core.data.sni,
&self.sig_schemes,
payload.get_alpn_extension(),
&payload.cipher_suites,
)
}
pub fn into_connection(mut self, config: Arc<ServerConfig>) -> Result<ServerConnection, Error> {
self.connection
.set_max_fragment_size(config.max_fragment_size)?;
#[cfg(feature = "secret_extraction")]
{
self.connection.enable_secret_extraction = config.enable_secret_extraction;
}
let state = hs::ExpectClientHello::new(config, Vec::new());
let mut cx = hs::ServerContext::from(&mut self.connection);
let new = state.with_certified_key(
self.sig_schemes,
Self::client_hello_payload(&self.message),
&self.message,
&mut cx,
)?;
self.connection.replace_state(new);
Ok(ServerConnection {
inner: self.connection,
})
}
fn client_hello_payload(message: &Message) -> &ClientHelloPayload {
match &message.payload {
crate::msgs::message::MessagePayload::Handshake { parsed, .. } => match &parsed.payload
{
crate::msgs::handshake::HandshakePayload::ClientHello(ch) => ch,
_ => unreachable!(),
},
_ => unreachable!(),
}
}
}
struct Accepting;
impl State<ServerConnectionData> for Accepting {
fn handle(
self: Box<Self>,
_cx: &mut hs::ServerContext<'_>,
_m: Message,
) -> Result<Box<dyn State<ServerConnectionData>>, Error> {
Err(Error::General("unreachable state".into()))
}
}
pub(super) enum EarlyDataState {
New,
Accepted(ChunkVecBuffer),
Rejected,
}
impl Default for EarlyDataState {
fn default() -> Self {
Self::New
}
}
impl EarlyDataState {
pub(super) fn reject(&mut self) {
*self = Self::Rejected;
}
pub(super) fn accept(&mut self, max_size: usize) {
*self = Self::Accepted(ChunkVecBuffer::new(Some(max_size)));
}
fn was_accepted(&self) -> bool {
matches!(self, Self::Accepted(_))
}
pub(super) fn was_rejected(&self) -> bool {
matches!(self, Self::Rejected)
}
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
Self::Accepted(ref mut received) => received.read(buf),
_ => Err(io::Error::from(io::ErrorKind::BrokenPipe)),
}
}
#[cfg(read_buf)]
fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> {
match self {
Self::Accepted(ref mut received) => received.read_buf(cursor),
_ => Err(io::Error::from(io::ErrorKind::BrokenPipe)),
}
}
pub(super) fn take_received_plaintext(&mut self, bytes: Payload) -> bool {
let available = bytes.0.len();
match self {
Self::Accepted(ref mut received) if received.apply_limit(available) == available => {
received.append(bytes.0);
true
}
_ => false,
}
}
}
#[test]
fn test_read_in_new_state() {
assert_eq!(
format!("{:?}", EarlyDataState::default().read(&mut [0u8; 5])),
"Err(Kind(BrokenPipe))"
);
}
#[cfg(read_buf)]
#[test]
fn test_read_buf_in_new_state() {
use std::io::BorrowedBuf;
let mut buf = [0u8; 5];
let mut buf: BorrowedBuf<'_> = buf.as_mut_slice().into();
assert_eq!(
format!("{:?}", EarlyDataState::default().read_buf(buf.unfilled())),
"Err(Kind(BrokenPipe))"
);
}
impl ConnectionCore<ServerConnectionData> {
pub(crate) fn for_server(
config: Arc<ServerConfig>,
extra_exts: Vec<ServerExtension>,
) -> Result<Self, Error> {
let mut common = CommonState::new(Side::Server);
common.set_max_fragment_size(config.max_fragment_size)?;
#[cfg(feature = "secret_extraction")]
{
common.enable_secret_extraction = config.enable_secret_extraction;
}
Ok(Self::new(
Box::new(hs::ExpectClientHello::new(config, extra_exts)),
ServerConnectionData::default(),
common,
))
}
pub(crate) fn reject_early_data(&mut self) {
assert!(
self.common_state.is_handshaking(),
"cannot retroactively reject early data"
);
self.data.early_data.reject();
}
pub(crate) fn get_sni_str(&self) -> Option<&str> {
self.data.get_sni_str()
}
}
#[derive(Default)]
pub struct ServerConnectionData {
pub(super) sni: Option<DnsName>,
pub(super) received_resumption_data: Option<Vec<u8>>,
pub(super) resumption_data: Vec<u8>,
pub(super) early_data: EarlyDataState,
}
impl ServerConnectionData {
pub(super) fn get_sni_str(&self) -> Option<&str> {
self.sni.as_ref().map(AsRef::as_ref)
}
}
impl crate::conn::SideData for ServerConnectionData {}