mirror of
https://github.com/rustls/rustls.git
synced 2026-10-29 10:21:44 +08:00
115 lines
4.0 KiB
Rust
115 lines
4.0 KiB
Rust
use std::io::Write;
|
|
use std::sync::Arc;
|
|
|
|
use rustls::crypto::Identity;
|
|
use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
|
|
use rustls::server::Acceptor;
|
|
use rustls::{Connection, ServerConfig, VecBuffer};
|
|
use rustls_util::{KeyLogFile, complete_io};
|
|
|
|
fn main() {
|
|
env_logger::init();
|
|
|
|
let pki = TestPki::new();
|
|
let server_config = pki.server_config();
|
|
|
|
let listener = std::net::TcpListener::bind(format!("[::]:{}", 4443)).unwrap();
|
|
for stream in listener.incoming() {
|
|
let mut stream = stream.unwrap();
|
|
let mut acceptor = Acceptor::default();
|
|
let mut buf = VecBuffer::default();
|
|
|
|
let accepted = loop {
|
|
buf.read(&mut stream).unwrap();
|
|
if let Some(accepted) = acceptor.accept(&mut buf).unwrap() {
|
|
break accepted;
|
|
}
|
|
};
|
|
|
|
match accepted.into_connection(server_config.clone()) {
|
|
Ok(mut conn) => {
|
|
let msg = concat!(
|
|
"HTTP/1.1 200 OK\r\n",
|
|
"Connection: Closed\r\n",
|
|
"Content-Type: text/html\r\n",
|
|
"\r\n",
|
|
"<h1>Hello World!</h1>\r\n"
|
|
)
|
|
.as_bytes();
|
|
|
|
// Note: do not use `unwrap()` on IO in real programs!
|
|
conn.writer().write_all(msg).unwrap();
|
|
conn.write_tls(&mut stream).unwrap();
|
|
complete_io(&mut stream, &mut buf, &mut conn).unwrap();
|
|
|
|
conn.send_close_notify();
|
|
conn.write_tls(&mut stream).unwrap();
|
|
complete_io(&mut stream, &mut buf, &mut conn).unwrap();
|
|
}
|
|
Err((err, _)) => {
|
|
eprintln!("{err}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct TestPki {
|
|
server_cert_der: CertificateDer<'static>,
|
|
server_key_der: PrivateKeyDer<'static>,
|
|
}
|
|
|
|
impl TestPki {
|
|
fn new() -> Self {
|
|
let alg = &rcgen::PKCS_ECDSA_P256_SHA256;
|
|
let mut ca_params = rcgen::CertificateParams::new(Vec::new()).unwrap();
|
|
ca_params
|
|
.distinguished_name
|
|
.push(rcgen::DnType::OrganizationName, "Provider Server Example");
|
|
ca_params
|
|
.distinguished_name
|
|
.push(rcgen::DnType::CommonName, "Example CA");
|
|
ca_params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained);
|
|
ca_params.key_usages = vec![
|
|
rcgen::KeyUsagePurpose::KeyCertSign,
|
|
rcgen::KeyUsagePurpose::DigitalSignature,
|
|
];
|
|
let ca_key = rcgen::KeyPair::generate_for(alg).unwrap();
|
|
let ca = rcgen::Issuer::new(ca_params, ca_key);
|
|
|
|
// Create a server end entity cert issued by the CA.
|
|
let mut server_ee_params =
|
|
rcgen::CertificateParams::new(vec!["localhost".to_string()]).unwrap();
|
|
server_ee_params.is_ca = rcgen::IsCa::NoCa;
|
|
server_ee_params.extended_key_usages = vec![rcgen::ExtendedKeyUsagePurpose::ServerAuth];
|
|
let server_key = rcgen::KeyPair::generate_for(alg).unwrap();
|
|
|
|
let server_cert = server_ee_params
|
|
.signed_by(&server_key, &ca)
|
|
.unwrap();
|
|
Self {
|
|
server_cert_der: server_cert.into(),
|
|
// TODO(XXX): update below once https://github.com/rustls/rcgen/issues/260 is resolved.
|
|
server_key_der: PrivatePkcs8KeyDer::from(server_key.serialize_der()).into(),
|
|
}
|
|
}
|
|
|
|
fn server_config(self) -> Arc<ServerConfig> {
|
|
let provider = Arc::new(rustls_provider_example::provider());
|
|
let mut server_config = ServerConfig::builder(provider.clone())
|
|
.with_no_client_auth()
|
|
.with_single_cert(
|
|
Arc::new(Identity::from_cert_chain(vec![self.server_cert_der]).unwrap()),
|
|
self.server_key_der,
|
|
)
|
|
.unwrap();
|
|
|
|
server_config.key_log = Arc::new(KeyLogFile::new());
|
|
server_config.ticketer = provider
|
|
.ticketer_factory
|
|
.ticketer()
|
|
.ok();
|
|
|
|
Arc::new(server_config)
|
|
}
|
|
}
|