diff options
Diffstat (limited to 'src/bin/server/tls.rs')
| -rw-r--r-- | src/bin/server/tls.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/bin/server/tls.rs b/src/bin/server/tls.rs new file mode 100644 index 0000000..acf3315 --- /dev/null +++ b/src/bin/server/tls.rs | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | use std::io::{Read, Write}; | ||
| 2 | use std::net::TcpStream; | ||
| 3 | |||
| 4 | #[derive(Clone)] | ||
| 5 | pub struct TlsServer { | ||
| 6 | acceptor: native_tls::TlsAcceptor, | ||
| 7 | } | ||
| 8 | |||
| 9 | impl TlsServer { | ||
| 10 | pub fn new( | ||
| 11 | cert_path: &str, | ||
| 12 | _key_path: &str, | ||
| 13 | unsafe_mode: bool, | ||
| 14 | ) -> Result<Self, Box<dyn std::error::Error>> { | ||
| 15 | let cert_data = if unsafe_mode { | ||
| 16 | if std::path::Path::new(cert_path).exists() { | ||
| 17 | std::fs::read(cert_path)? | ||
| 18 | } else { | ||
| 19 | return Err(format!( | ||
| 20 | "Certificate file '{}' not found. In --unsafe mode, you must provide a valid PKCS12 certificate file.\n\ | ||
| 21 | You can generate one with:\n\ | ||
| 22 | openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes\n\ | ||
| 23 | openssl pkcs12 -export -out identity.p12 -inkey key.pem -in cert.pem", | ||
| 24 | cert_path | ||
| 25 | ).into()); | ||
| 26 | } | ||
| 27 | } else { | ||
| 28 | std::fs::read(cert_path)? | ||
| 29 | }; | ||
| 30 | |||
| 31 | let identity = native_tls::Identity::from_pkcs12(&cert_data, "")?; | ||
| 32 | let acceptor = native_tls::TlsAcceptor::new(identity)?; | ||
| 33 | |||
| 34 | Ok(Self { acceptor }) | ||
| 35 | } | ||
| 36 | |||
| 37 | pub fn accept(&self, stream: TcpStream) -> Result<TlsStream, Box<dyn std::error::Error>> { | ||
| 38 | let stream = self.acceptor.accept(stream)?; | ||
| 39 | Ok(TlsStream::new(stream)) | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | pub struct TlsStream { | ||
| 44 | stream: native_tls::TlsStream<TcpStream>, | ||
| 45 | } | ||
| 46 | |||
| 47 | impl TlsStream { | ||
| 48 | pub fn new(stream: native_tls::TlsStream<TcpStream>) -> Self { | ||
| 49 | Self { stream } | ||
| 50 | } | ||
| 51 | |||
| 52 | pub fn read_line(&mut self, s: &mut String) -> std::io::Result<usize> { | ||
| 53 | let mut buf = [0u8; 1024]; | ||
| 54 | loop { | ||
| 55 | match self.stream.read(&mut buf) { | ||
| 56 | Ok(0) => return Ok(0), | ||
| 57 | Ok(n) => { | ||
| 58 | let chunk = std::str::from_utf8(&buf[..n]).unwrap_or(""); | ||
| 59 | s.push_str(chunk); | ||
| 60 | if s.contains('\n') { | ||
| 61 | return Ok(n); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | Err(e) => return Err(e), | ||
| 65 | } | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | pub fn write_line(&mut self, msg: &str) -> std::io::Result<()> { | ||
| 70 | use std::io::Write; | ||
| 71 | self.stream.write_all(msg.as_bytes())?; | ||
| 72 | self.stream.write_all(b"\n")?; | ||
| 73 | self.stream.flush()?; | ||
| 74 | Ok(()) | ||
| 75 | } | ||
| 76 | |||
| 77 | pub fn peer_addr(&self) -> std::io::Result<std::net::SocketAddr> { | ||
| 78 | self.stream.get_ref().peer_addr() | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | impl Read for TlsStream { | ||
| 83 | fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { | ||
| 84 | self.stream.read(buf) | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | impl Write for TlsStream { | ||
| 89 | fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { | ||
| 90 | self.stream.write(buf) | ||
| 91 | } | ||
| 92 | |||
| 93 | fn flush(&mut self) -> std::io::Result<()> { | ||
| 94 | self.stream.flush() | ||
| 95 | } | ||
| 96 | } | ||
