Added redirect and cgienv

This commit is contained in:
int 80h
2020-05-13 21:42:00 -04:00
parent 929a11a91c
commit dfae3705c4
12 changed files with 178 additions and 130 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/target/
Cargo.lock
**/*.rs.bk
.gemgit

7
README
View File

@@ -8,6 +8,7 @@ A gemini server written in rust.
- CGI - CGI
- User directories - User directories
- Reverse proxy - Reverse proxy
- Redirect
## Installation and running ## Installation and running
@@ -19,7 +20,11 @@ A gemini server written in rust.
## Create server key/cert pairs ## Create server key/cert pairs
## CGI ## CGI Environments
These variables are preset for you. If you need more you can define them in the
config file under "cgienv"
- GEMINI_URL - GEMINI_URL
- SERVER_NAME - SERVER_NAME
- SERVER_PROTOCOL - SERVER_PROTOCOL

View File

@@ -6,10 +6,10 @@ const BASE: &'static str = "gemini://example.com/";
fn main() { fn main() {
let query = match env::var("QUERY_STRING") { let query = match env::var("QUERY_STRING") {
Ok(q) => q, Ok(q) => q,
_ => { _ => {
println!("10\tGopher url:\r\n"); println!("10\tGopher url:\r\n");
return; return;
}, }
}; };
println!("30\t{}{}\r\n", BASE, query); println!("30\t{}{}\r\n", BASE, query);
} }

View File

@@ -2,6 +2,8 @@ port = 1965
# use "::" for ipv6 and ipv4 or "0.0.0.0" for ipv4 only # use "::" for ipv6 and ipv4 or "0.0.0.0" for ipv4 only
host = "::" host = "::"
# There must be at least 1 server tag
# Server 1
[[server]] [[server]]
hostname = "example.com" hostname = "example.com"
dir = "/path/to/serv" dir = "/path/to/serv"
@@ -9,12 +11,17 @@ key = "/path/to/key"
cert = "/path/to/cert" cert = "/path/to/cert"
# cgi dir is optional # cgi dir is optional
cgi = "/path/to/cgi-bin/" cgi = "/path/to/cgi-bin/"
# usrdir is optional. it'll look in /home/~usr/public_gemini # cgienv is optional
cgienv = { "GIT_PROJECT_ROOT" = "/srv/git" }
# usrdir is optional. it'll look in /home/usr/public_gemini
usrdir = true usrdir = true
# proxy is optional # proxy is optional
# path is what comes after the hostname e.g. example.com/path # path is what comes after the hostname e.g. example.com/path
proxy { path = "localhost:1966" } proxy { path = "localhost:1966" }
# redirect is optional
redirect = { "/redirect" = "/", "/newdomain" = "gemini://example.net" }
# Server 2
[[server]] [[server]]
hostname = "example.net" hostname = "example.net"
dir = "/path/to/serv/" dir = "/path/to/serv/"

View File

@@ -1,14 +1,20 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::io; use std::io;
use std::path::{PathBuf}; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use url::Url; use url::Url;
use crate::status::Status; use crate::config;
use crate::conn; use crate::conn;
use crate::logger; use crate::logger;
use crate::status::Status;
pub async fn cgi(mut con: conn::Connection, path: PathBuf, url: Url) -> Result<(), io::Error> { pub async fn cgi(
mut con: conn::Connection,
srv: &config::ServerCfg,
path: PathBuf,
url: Url,
) -> Result<(), io::Error> {
let mut envs = HashMap::new(); let mut envs = HashMap::new();
envs.insert("GATEWAY_INTERFACE", "CGI/1.1"); envs.insert("GATEWAY_INTERFACE", "CGI/1.1");
envs.insert("GEMINI_URL", url.as_str()); envs.insert("GEMINI_URL", url.as_str());
@@ -26,6 +32,12 @@ pub async fn cgi(mut con: conn::Connection, path: PathBuf, url: Url) -> Result<(
envs.insert("QUERY_STRING", q); envs.insert("QUERY_STRING", q);
} }
if srv.cgienv.len() != 0 {
for (k, v) in srv.cgienv.iter() {
envs.insert(&k, &v);
}
};
let cmd = Command::new(path.to_str().unwrap()) let cmd = Command::new(path.to_str().unwrap())
.env_clear() .env_clear()
.envs(&envs) .envs(&envs)

View File

@@ -1,8 +1,8 @@
extern crate serde_derive; extern crate serde_derive;
extern crate toml; extern crate toml;
use std::collections::HashMap; use std::collections::HashMap;
use toml::de::Error;
use std::path::Path; use std::path::Path;
use toml::de::Error;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
pub struct Config { pub struct Config {
@@ -18,8 +18,10 @@ pub struct Server {
pub key: String, pub key: String,
pub cert: String, pub cert: String,
pub cgi: Option<String>, pub cgi: Option<String>,
pub cgienv: Option<HashMap<String, String>>,
pub usrdir: Option<bool>, pub usrdir: Option<bool>,
pub proxy: Option<HashMap<String, String>>, pub proxy: Option<HashMap<String, String>>,
pub redirect: Option<HashMap<String, String>>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -29,9 +31,11 @@ pub struct ServerCfg {
pub key: String, pub key: String,
pub cert: String, pub cert: String,
pub cgi: String, pub cgi: String,
pub cgienv: HashMap<String, String>,
pub usrdir: bool, pub usrdir: bool,
pub port: u16, pub port: u16,
pub proxy: HashMap<String, String>, pub proxy: HashMap<String, String>,
pub redirect: HashMap<String, String>,
} }
impl Config { impl Config {
@@ -54,18 +58,36 @@ impl Config {
let mut pmap = HashMap::new(); let mut pmap = HashMap::new();
match &srv.proxy { match &srv.proxy {
Some(pr) => pmap = pr.clone(), Some(pr) => pmap = pr.clone(),
None => {}, None => {}
}; };
map.insert(srv.hostname.clone(), ServerCfg {
hostname: srv.hostname.clone(), let mut rmap = HashMap::new();
dir: srv.dir.clone(), match &srv.redirect {
key: srv.key.clone(), Some(r) => rmap = r.clone(),
cert: srv.cert.clone(), None => {}
cgi: cgi, };
usrdir: usrdir,
port: self.port.clone(), let mut cmap = HashMap::new();
proxy: pmap.clone(), match &srv.cgienv {
}); Some(c) => cmap = c.clone(),
None => {}
};
map.insert(
srv.hostname.clone(),
ServerCfg {
hostname: srv.hostname.clone(),
dir: srv.dir.clone(),
key: srv.key.clone(),
cert: srv.cert.clone(),
cgi: cgi,
cgienv: cmap.clone(),
usrdir: usrdir,
port: self.port.clone(),
proxy: pmap.clone(),
redirect: rmap.clone(),
},
);
} }
map map
} }

View File

@@ -12,36 +12,32 @@ pub struct Connection {
} }
impl Connection { impl Connection {
pub async fn send_status( pub async fn send_status(&mut self, stat: Status, meta: Option<&str>) -> Result<(), io::Error> {
&mut self, self.send_body(stat, meta, None).await?;
stat: Status, Ok(())
meta: Option<&str>,
) -> Result<(), io::Error> {
self.send_body(stat, meta, None).await?;
Ok(())
}
pub async fn send_body(
&mut self,
stat: Status,
meta: Option<&str>,
body: Option<String>,
) -> Result<(), io::Error> {
let meta = match meta {
Some(m) => m,
None => &stat.to_str(),
};
let mut s = format!("{}\t{}\r\n", stat as u8, meta);
if let Some(b) = body {
s += &b;
} }
self.send_raw(s.as_bytes()).await?;
Ok(())
}
pub async fn send_raw(&mut self, body: &[u8]) -> Result<(), io::Error> { pub async fn send_body(
self.stream.write_all(body).await?; &mut self,
self.stream.flush().await?; stat: Status,
Ok(()) meta: Option<&str>,
} body: Option<String>,
) -> Result<(), io::Error> {
let meta = match meta {
Some(m) => m,
None => &stat.to_str(),
};
let mut s = format!("{}\t{}\r\n", stat as u8, meta);
if let Some(b) = body {
s += &b;
}
self.send_raw(s.as_bytes()).await?;
Ok(())
}
pub async fn send_raw(&mut self, body: &[u8]) -> Result<(), io::Error> {
self.stream.write_all(body).await?;
self.stream.flush().await?;
Ok(())
}
} }

View File

@@ -1,16 +1,10 @@
use std::net::SocketAddr;
use log::{info, warn};
use crate::status; use crate::status;
use log::{info, warn};
use std::net::SocketAddr;
pub fn logger(addr: SocketAddr, stat: status::Status, req: &str) { pub fn logger(addr: SocketAddr, stat: status::Status, req: &str) {
match stat as u8 { match stat as u8 {
20..=29 => info!( 20..=29 => info!("remote={} status={} request={}", addr, stat as u8, req),
"remote={} status={} request={}", _ => warn!("remote={} status={} request={}", addr, stat as u8, req),
addr, stat as u8, req
),
_ => warn!(
"remote={} status={} request={}",
addr, stat as u8, req
),
} }
} }

View File

@@ -2,30 +2,30 @@
extern crate serde_derive; extern crate serde_derive;
use futures_util::future::TryFutureExt; use futures_util::future::TryFutureExt;
use mime;
use mime_guess;
use openssl::ssl::NameType;
use std::env;
use std::fs; use std::fs;
use std::fs::File; use std::fs::File;
use std::io::{self, BufReader, BufRead}; use std::io::{self, BufRead, BufReader};
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::env;
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tokio::prelude::*; use tokio::prelude::*;
use tokio::runtime; use tokio::runtime;
use openssl::ssl::NameType;
use url::Url; use url::Url;
use mime_guess;
use mime;
mod cgi; mod cgi;
mod config; mod config;
mod status; mod status;
use status::Status; use status::Status;
mod tls;
mod conn; mod conn;
mod revproxy;
mod logger; mod logger;
mod revproxy;
mod tls;
fn get_mime(path: &PathBuf) -> String { fn get_mime(path: &PathBuf) -> String {
let mut mime = "text/gemini"; let mut mime = "text/gemini";
@@ -38,14 +38,15 @@ fn get_mime(path: &PathBuf) -> String {
if ext != "gemini" { if ext != "gemini" {
m = mime_guess::from_ext(ext).first().unwrap(); m = mime_guess::from_ext(ext).first().unwrap();
mime = m.essence_str(); mime = m.essence_str();
} }
mime.to_string() mime.to_string()
} }
async fn get_binary(mut con: conn::Connection, path:PathBuf, meta: String) -> io::Result<()> { async fn get_binary(mut con: conn::Connection, path: PathBuf, meta: String) -> io::Result<()> {
let fd = File::open(path)?; let fd = File::open(path)?;
let mut reader = BufReader::with_capacity(1024*1024,fd); let mut reader = BufReader::with_capacity(1024 * 1024, fd);
con.send_status(status::Status::Success, Some(&meta)).await?; con.send_status(status::Status::Success, Some(&meta))
.await?;
loop { loop {
let len = { let len = {
let buf = reader.fill_buf()?; let buf = reader.fill_buf()?;
@@ -53,7 +54,7 @@ async fn get_binary(mut con: conn::Connection, path:PathBuf, meta: String) -> io
buf.len() buf.len()
}; };
if len == 0 { if len == 0 {
break break;
} }
reader.consume(len); reader.consume(len);
} }
@@ -74,7 +75,7 @@ fn get_content(path: PathBuf, u: url::Url) -> Result<String, io::Error> {
let m = file.metadata()?; let m = file.metadata()?;
let perm = m.permissions(); let perm = m.permissions();
if perm.mode() & 0o0444 != 0o0444 { if perm.mode() & 0o0444 != 0o0444 {
continue continue;
} }
let file = file.path(); let file = file.path();
let p = file.strip_prefix(&path).unwrap(); let p = file.strip_prefix(&path).unwrap();
@@ -88,9 +89,11 @@ fn get_content(path: PathBuf, u: url::Url) -> Result<String, io::Error> {
return Ok(list); return Ok(list);
} }
// TODO Rewrite this monster.
// TODO Rewrite this monster. async fn handle_connection(
async fn handle_connection(mut con: conn::Connection, srv: &config::ServerCfg) -> Result<(), io::Error> { mut con: conn::Connection,
srv: &config::ServerCfg,
) -> Result<(), io::Error> {
let mut buffer = [0; 1024]; let mut buffer = [0; 1024];
con.stream.read(&mut buffer).await?; con.stream.read(&mut buffer).await?;
let mut request = match String::from_utf8(buffer[..].to_vec()) { let mut request = match String::from_utf8(buffer[..].to_vec()) {
@@ -98,7 +101,7 @@ async fn handle_connection(mut con: conn::Connection, srv: &config::ServerCfg) -
Err(_) => { Err(_) => {
logger::logger(con.peer_addr, Status::BadRequest, ""); logger::logger(con.peer_addr, Status::BadRequest, "");
con.send_status(Status::BadRequest, None).await?; con.send_status(Status::BadRequest, None).await?;
return Ok(()) return Ok(());
} }
}; };
if request.starts_with("//") { if request.starts_with("//") {
@@ -110,7 +113,7 @@ async fn handle_connection(mut con: conn::Connection, srv: &config::ServerCfg) -
Err(_) => { Err(_) => {
logger::logger(con.peer_addr, Status::BadRequest, &request); logger::logger(con.peer_addr, Status::BadRequest, &request);
con.send_status(Status::BadRequest, None).await?; con.send_status(Status::BadRequest, None).await?;
return Ok(()) return Ok(());
} }
}; };
@@ -121,52 +124,62 @@ async fn handle_connection(mut con: conn::Connection, srv: &config::ServerCfg) -
} }
match url.port() { match url.port() {
Some(p) => { if p != srv.port { Some(p) => {
logger::logger(con.peer_addr, Status::ProxyRequestRefused, &request); if p != srv.port {
con.send_status(status::Status::ProxyRequestRefused, None).await?; logger::logger(con.peer_addr, Status::ProxyRequestRefused, &request);
}}, con.send_status(status::Status::ProxyRequestRefused, None)
.await?;
}
}
None => {} None => {}
} }
if url.scheme() != "gemini" { if url.scheme() != "gemini" {
logger::logger(con.peer_addr, Status::ProxyRequestRefused, &request); logger::logger(con.peer_addr, Status::ProxyRequestRefused, &request);
con.send_status(Status::ProxyRequestRefused, None) con.send_status(Status::ProxyRequestRefused, None).await?;
.await?;
return Ok(()); return Ok(());
} }
if srv.redirect.len() != 0 {
let u = url.path().trim_end_matches("/");
match srv.redirect.get(u) {
Some(r) => {
logger::logger(con.peer_addr, Status::RedirectTemporary, &request);
con.send_status(Status::RedirectTemporary, Some(r)).await?;
return Ok(());
}
None => {}
}
}
if srv.proxy.len() != 0 { if srv.proxy.len() != 0 {
match url.path_segments().map(|c| c.collect::<Vec<_>>()) { match url.path_segments().map(|c| c.collect::<Vec<_>>()) {
Some(s) => { Some(s) => match srv.proxy.get(s[0]) {
match srv.proxy.get(s[0]) { Some(p) => {
Some(p) => { revproxy::proxy(p.to_string(), url, con).await?;
revproxy::proxy(p.to_string(), url, con).await?; return Ok(());
return Ok(());
},
None => {},
} }
} None => {}
None => {}, },
} None => {}
}
} }
let mut path = PathBuf::new(); let mut path = PathBuf::new();
if url.path().starts_with("/~") && srv.usrdir == true{ if url.path().starts_with("/~") && srv.usrdir == true {
let usr = url.path().trim_start_matches("/~"); let usr = url.path().trim_start_matches("/~");
let usr: Vec<&str> = usr.splitn(2, "/").collect(); let usr: Vec<&str> = usr.splitn(2, "/").collect();
path.push("/home/"); path.push("/home/");
if usr.len() == 2 { if usr.len() == 2 {
path.push(format!("{}/{}/{}", usr[0], "public_gemini", usr[1])); path.push(format!("{}/{}/{}", usr[0], "public_gemini", usr[1]));
} else { } else {
path.push(format!("{}/{}/",usr[0], "public_gemini")); path.push(format!("{}/{}/", usr[0], "public_gemini"));
} }
} else { } else {
path.push(&srv.dir); path.push(&srv.dir);
if url.path() != "" || url.path() != "/" { if url.path() != "" || url.path() != "/" {
path.push(url.path().trim_start_matches("/")); path.push(url.path().trim_start_matches("/"));
} }
} }
if !path.exists() { if !path.exists() {
@@ -197,7 +210,7 @@ async fn handle_connection(mut con: conn::Connection, srv: &config::ServerCfg) -
if perm.mode() & 0o0444 != 0o444 { if perm.mode() & 0o0444 != 0o444 {
let mut p = path.clone(); let mut p = path.clone();
p.pop(); p.pop();
path.push(format!("{}/",p.display())); path.push(format!("{}/", p.display()));
meta = fs::metadata(&path).expect("Unable to read metadata"); meta = fs::metadata(&path).expect("Unable to read metadata");
perm = meta.permissions(); perm = meta.permissions();
} }
@@ -207,8 +220,8 @@ async fn handle_connection(mut con: conn::Connection, srv: &config::ServerCfg) -
// TODO add timeout // TODO add timeout
if srv.cgi.trim_end_matches("/") == path.parent().unwrap().to_str().unwrap() { if srv.cgi.trim_end_matches("/") == path.parent().unwrap().to_str().unwrap() {
if perm.mode() & 0o0111 == 0o0111 { if perm.mode() & 0o0111 == 0o0111 {
cgi::cgi(con, path, url).await?; cgi::cgi(con, srv, path, url).await?;
return Ok(()); return Ok(());
} else { } else {
logger::logger(con.peer_addr, Status::CGIError, &request); logger::logger(con.peer_addr, Status::CGIError, &request);
con.send_status(Status::CGIError, None).await?; con.send_status(Status::CGIError, None).await?;
@@ -229,12 +242,8 @@ async fn handle_connection(mut con: conn::Connection, srv: &config::ServerCfg) -
return Ok(()); return Ok(());
} }
let content = get_content(path, url)?; let content = get_content(path, url)?;
con.send_body( con.send_body(status::Status::Success, Some(mime.as_str()), Some(content))
status::Status::Success, .await?;
Some(mime.as_str()),
Some(content),
)
.await?;
logger::logger(con.peer_addr, Status::Success, &request); logger::logger(con.peer_addr, Status::Success, &request);
Ok(()) Ok(())
@@ -279,7 +288,9 @@ fn main() -> io::Result<()> {
let cmap = cmap.clone(); let cmap = cmap.clone();
let fut = async move { let fut = async move {
let mut stream = tokio_openssl::accept(&acceptor, stream).await.expect("Couldn't accept"); let mut stream = tokio_openssl::accept(&acceptor, stream)
.await
.expect("Couldn't accept");
let sni = match stream.ssl().servername(NameType::HOST_NAME) { let sni = match stream.ssl().servername(NameType::HOST_NAME) {
Some(s) => s, Some(s) => s,
None => return Ok(()), None => return Ok(()),
@@ -292,13 +303,10 @@ fn main() -> io::Result<()> {
stream.write_all(b"59\tNotFound!\r\n").await?; stream.write_all(b"59\tNotFound!\r\n").await?;
stream.flush().await?; stream.flush().await?;
return Ok(()); return Ok(());
}, }
};
let con = conn::Connection {
stream,
peer_addr,
}; };
let con = conn::Connection { stream, peer_addr };
handle_connection(con, srv).await?; handle_connection(con, srv).await?;
Ok(()) as io::Result<()> Ok(()) as io::Result<()>

View File

@@ -1,12 +1,12 @@
use openssl::ssl::{SslConnector, SslMethod};
use std::io; use std::io;
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream; use tokio::net::TcpStream;
use openssl::ssl::{SslConnector, SslMethod};
use crate::conn; use crate::conn;
use crate::status::Status;
use crate::logger; use crate::logger;
use crate::status::Status;
pub async fn proxy(addr: String, u: url::Url, mut con: conn::Connection) -> Result<(), io::Error> { pub async fn proxy(addr: String, u: url::Url, mut con: conn::Connection) -> Result<(), io::Error> {
let p: Vec<&str> = u.path().trim_start_matches("/").splitn(2, "/").collect(); let p: Vec<&str> = u.path().trim_start_matches("/").splitn(2, "/").collect();
@@ -18,7 +18,7 @@ pub async fn proxy(addr: String, u: url::Url, mut con: conn::Connection) -> Resu
if p[1] == "" || p[1] == "/" { if p[1] == "" || p[1] == "/" {
logger::logger(con.peer_addr, Status::NotFound, u.as_str()); logger::logger(con.peer_addr, Status::NotFound, u.as_str());
con.send_status(Status::NotFound, None).await?; con.send_status(Status::NotFound, None).await?;
return Ok(()) return Ok(());
} }
let addr = addr let addr = addr
.to_socket_addrs()? .to_socket_addrs()?
@@ -34,20 +34,20 @@ pub async fn proxy(addr: String, u: url::Url, mut con: conn::Connection) -> Resu
Err(_) => { Err(_) => {
logger::logger(con.peer_addr, Status::ProxyError, u.as_str()); logger::logger(con.peer_addr, Status::ProxyError, u.as_str());
con.send_status(Status::ProxyError, None).await?; con.send_status(Status::ProxyError, None).await?;
return Ok(()) return Ok(());
}, }
}; };
let mut stream = match tokio_openssl::connect(config, "localhost", stream).await { let mut stream = match tokio_openssl::connect(config, "localhost", stream).await {
Ok(s) => s, Ok(s) => s,
Err(_) => { Err(_) => {
logger::logger(con.peer_addr, Status::ProxyError, u.as_str()); logger::logger(con.peer_addr, Status::ProxyError, u.as_str());
con.send_status(Status::ProxyError, None).await?; con.send_status(Status::ProxyError, None).await?;
return Ok(()) return Ok(());
}, }
}; };
stream.write_all(p[1].as_bytes()).await?; stream.write_all(p[1].as_bytes()).await?;
stream.flush().await?; stream.flush().await?;
let mut buf = vec![]; let mut buf = vec![];
stream.read_to_end(&mut buf).await?; stream.read_to_end(&mut buf).await?;
// let req = String::from_utf8(buf[..].to_vec()).unwrap(); // let req = String::from_utf8(buf[..].to_vec()).unwrap();

View File

@@ -52,7 +52,7 @@ impl Status {
Status::FutureCertificateRejected => "Future Certificate Rejected", Status::FutureCertificateRejected => "Future Certificate Rejected",
Status::ExpiredCertificateRejected => "Expired Certificate Rejected", Status::ExpiredCertificateRejected => "Expired Certificate Rejected",
}; };
return meta return meta;
} }
} }
@@ -61,4 +61,3 @@ impl fmt::Display for Status {
write!(f, "{:?}", self) write!(f, "{:?}", self)
} }
} }

View File

@@ -2,12 +2,12 @@ extern crate openssl;
extern crate tokio_openssl; extern crate tokio_openssl;
use std::collections::HashMap; use std::collections::HashMap;
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use openssl::ssl::SniError;
use openssl::error::ErrorStack; use openssl::error::ErrorStack;
use openssl::ssl::NameType;
use openssl::ssl::SniError;
use openssl::ssl::SslContextBuilder; use openssl::ssl::SslContextBuilder;
use openssl::ssl::SslVersion; use openssl::ssl::SslVersion;
use openssl::ssl::NameType; use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use crate::config; use crate::config;
@@ -22,15 +22,15 @@ pub fn acceptor_conf(cfg: config::Config) -> Result<SslAcceptor, ErrorStack> {
Ok(c) => c, Ok(c) => c,
Err(e) => { Err(e) => {
eprintln!("Error: Can't load key file"); eprintln!("Error: Can't load key file");
return Err(e) return Err(e);
}, }
}; };
match ctx.set_certificate_chain_file(&server.cert) { match ctx.set_certificate_chain_file(&server.cert) {
Ok(c) => c, Ok(c) => c,
Err(e) => { Err(e) => {
eprintln!("Error: Can't load cert file"); eprintln!("Error: Can't load cert file");
return Err(e) return Err(e);
}, }
}; };
let ctx = ctx.build(); let ctx = ctx.build();
map.insert(server.hostname.clone(), ctx.clone()); map.insert(server.hostname.clone(), ctx.clone());
@@ -53,7 +53,8 @@ pub fn acceptor_conf(cfg: config::Config) -> Result<SslAcceptor, ErrorStack> {
} else { } else {
&map.get(&"default".to_string()).expect("Can't get default") &map.get(&"default".to_string()).expect("Can't get default")
} }
}).expect("Can't get sni"); })
.expect("Can't get sni");
Ok(()) Ok(())
}); });
Ok(acceptor.build()) Ok(acceptor.build())