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
90
91
92
93
94
95
96
|
use std::io::{Read, Write};
use std::net::TcpStream;
#[derive(Clone)]
pub struct TlsServer {
acceptor: native_tls::TlsAcceptor,
}
impl TlsServer {
pub fn new(
cert_path: &str,
_key_path: &str,
unsafe_mode: bool,
) -> Result<Self, Box<dyn std::error::Error>> {
let cert_data = if unsafe_mode {
if std::path::Path::new(cert_path).exists() {
std::fs::read(cert_path)?
} else {
return Err(format!(
"Certificate file '{}' not found. In --unsafe mode, you must provide a valid PKCS12 certificate file.\n\
You can generate one with:\n\
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes\n\
openssl pkcs12 -export -out identity.p12 -inkey key.pem -in cert.pem",
cert_path
).into());
}
} else {
std::fs::read(cert_path)?
};
let identity = native_tls::Identity::from_pkcs12(&cert_data, "")?;
let acceptor = native_tls::TlsAcceptor::new(identity)?;
Ok(Self { acceptor })
}
pub fn accept(&self, stream: TcpStream) -> Result<TlsStream, Box<dyn std::error::Error>> {
let stream = self.acceptor.accept(stream)?;
Ok(TlsStream::new(stream))
}
}
pub struct TlsStream {
stream: native_tls::TlsStream<TcpStream>,
}
impl TlsStream {
pub fn new(stream: native_tls::TlsStream<TcpStream>) -> Self {
Self { stream }
}
pub fn read_line(&mut self, s: &mut String) -> std::io::Result<usize> {
let mut buf = [0u8; 1024];
loop {
match self.stream.read(&mut buf) {
Ok(0) => return Ok(0),
Ok(n) => {
let chunk = std::str::from_utf8(&buf[..n]).unwrap_or("");
s.push_str(chunk);
if s.contains('\n') {
return Ok(n);
}
}
Err(e) => return Err(e),
}
}
}
pub fn write_line(&mut self, msg: &str) -> std::io::Result<()> {
use std::io::Write;
self.stream.write_all(msg.as_bytes())?;
self.stream.write_all(b"\n")?;
self.stream.flush()?;
Ok(())
}
pub fn peer_addr(&self) -> std::io::Result<std::net::SocketAddr> {
self.stream.get_ref().peer_addr()
}
}
impl Read for TlsStream {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.stream.read(buf)
}
}
impl Write for TlsStream {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.stream.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.stream.flush()
}
}
|