1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
mod certs;
pub use certs::generate_cert;

use core::task::{Context, Poll};
use fs::File;
use futures_util::stream::Stream;
use rustls::internal::pemfile;
use rustls::{NoClientAuth, ServerConfig};
use std::path::PathBuf;
use std::pin::Pin;
use std::sync::Arc;
use std::vec::Vec;
use std::{fs, io};
use tokio::net::TcpStream;
use tokio_rustls::{server::TlsStream, TlsAcceptor};

use crate::settings::get_wrangler_home_dir;

// Build TLS configuration
pub(super) fn get_tls_acceptor() -> Result<TlsAcceptor, failure::Error> {
    let home = get_wrangler_home_dir()?.join("config");
    let cert = home.join("dev-cert.pem");
    let privkey = home.join("dev-privkey.rsa");

    // Load public certificate
    let certs = load_certs(cert)?;

    // Load private key
    let key = load_private_key(privkey)?;

    // Do not use client certificate authentication.
    let mut cfg = ServerConfig::new(NoClientAuth::new());

    // Select a certificate to use.
    cfg.set_single_cert(certs, key)
        .map_err(|e| io_error(format!("{}", e)))?;

    Ok(TlsAcceptor::from(Arc::new(cfg)))
}

pub(super) fn io_error(err: String) -> io::Error {
    io::Error::new(io::ErrorKind::Other, err)
}

pub(super) struct HyperAcceptor<'a> {
    pub(super) acceptor:
        Pin<Box<dyn Stream<Item = Result<TlsStream<TcpStream>, io::Error>> + Send + 'a>>,
}

impl hyper::server::accept::Accept for HyperAcceptor<'_> {
    type Conn = TlsStream<TcpStream>;
    type Error = io::Error;

    fn poll_accept(
        mut self: Pin<&mut Self>,
        cx: &mut Context,
    ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
        Pin::new(&mut self.acceptor).poll_next(cx)
    }
}

fn get_tls_file(file: PathBuf) -> Result<File, io::Error> {
    File::open(&file)
}

// Load public certificate from file.
fn load_certs(file: PathBuf) -> io::Result<Vec<rustls::Certificate>> {
    // Open certificate file.
    let certfile = get_tls_file(file)?;
    let mut reader = io::BufReader::new(certfile);

    // Load and return certificate.
    pemfile::certs(&mut reader).map_err(|_| io_error("failed to load certificate".into()))
}

// Load private key from file.
fn load_private_key(file: PathBuf) -> io::Result<rustls::PrivateKey> {
    // Open keyfile.
    let keyfile = get_tls_file(file)?;
    let mut reader = io::BufReader::new(keyfile);

    // Load and return a single private key.
    let keys = pemfile::pkcs8_private_keys(&mut reader)
        .map_err(|_| io_error("failed to load private key".into()))?;
    if keys.len() != 1 {
        return Err(io_error("expected a single private key".into()));
    }
    Ok(keys[0].clone())
}