config file support
This commit is contained in:
parent
39885844a2
commit
72c1e3c813
3 changed files with 95 additions and 51 deletions
17
doc/sheldond.conf
Normal file
17
doc/sheldond.conf
Normal file
|
@ -0,0 +1,17 @@
|
|||
# no virtual host support yet, so this is actually the only host
|
||||
default_host = localhost
|
||||
|
||||
# should be self explanatory
|
||||
gem_root = /var/gemini/
|
||||
|
||||
# you can define as many of these as you like
|
||||
listen = [::1]:1965
|
||||
listen = 127.0.0.1:1965
|
||||
|
||||
# privilige level for the server to drop to after initializing
|
||||
user = gem-data
|
||||
group = gem-data
|
||||
|
||||
# certificate data MUST be in PEM format right now
|
||||
cert_key = /etc/ssl/private/gemini-key.pem
|
||||
cert_chain = /etc/ssl/certs/gemini-chain.pem
|
97
src/main.rs
97
src/main.rs
|
@ -1,6 +1,9 @@
|
|||
mod mime;
|
||||
mod server;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::path::Path;
|
||||
|
||||
fn help() {
|
||||
let version = match option_env!("CARGO_PKG_VERSION") {
|
||||
|
@ -9,69 +12,73 @@ fn help() {
|
|||
};
|
||||
|
||||
println!("usage: sheldond {}", version);
|
||||
println!(" -h, --help\t\tdisplay this message");
|
||||
println!(" -l, --listen\t\tadd a listening address (you can define multiple)");
|
||||
println!(" -d, --default-host\tdefault hostname to listen for");
|
||||
println!(" -g, --gem-root\tpath to the gemini root, aka the folder to serve files from");
|
||||
println!(" --user\tuser to drop to after opening TLS socket");
|
||||
println!(" --group\tgroup to drop to after opening TLS socket");
|
||||
println!(" -c, --config\t\tpath to the configuration file");
|
||||
}
|
||||
|
||||
fn parse_args() -> Option<server::ServerConfig> {
|
||||
let mut has_addr = false;
|
||||
let mut has_host = false;
|
||||
let mut has_root = false;
|
||||
let mut has_user = false;
|
||||
let mut has_group = false;
|
||||
|
||||
let mut config = server::ServerConfig::new();
|
||||
fn parse_args() -> Option<String> {
|
||||
let mut args = env::args();
|
||||
loop {
|
||||
match args.next() {
|
||||
Some(arg) => {
|
||||
if arg == "-h" || arg == "--help" {
|
||||
return None;
|
||||
}
|
||||
if arg == "-l" || arg == "--listen" {
|
||||
let addr = args.next().unwrap();
|
||||
config.add_addr(addr);
|
||||
has_addr = true;
|
||||
}
|
||||
if arg == "-d" || arg == "--default-host" {
|
||||
let host = args.next().unwrap();
|
||||
config.set_default_host(host);
|
||||
has_host = true;
|
||||
}
|
||||
if arg == "-g" || arg == "--gem-root" {
|
||||
let gem_root = args.next().unwrap();
|
||||
config.set_gem_root(gem_root);
|
||||
has_root = true;
|
||||
}
|
||||
if arg == "--user" {
|
||||
let user = args.next().unwrap();
|
||||
config.set_user(user);
|
||||
has_user = true;
|
||||
}
|
||||
if arg == "--group" {
|
||||
let group = args.next().unwrap();
|
||||
config.set_group(group);
|
||||
has_group = true;
|
||||
if arg == "-c" || arg == "--config" {
|
||||
let config_fname = args.next().unwrap();
|
||||
return Some(config_fname);
|
||||
}
|
||||
}
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
if !has_addr || !has_host || !has_root || !has_user || !has_group {
|
||||
return None;
|
||||
None
|
||||
}
|
||||
|
||||
fn parse_config(fname: String) -> server::ServerConfig {
|
||||
let path = Path::new(&fname);
|
||||
let mut config = server::ServerConfig::new();
|
||||
|
||||
let file = match File::open(path) {
|
||||
Ok(file) => BufReader::new(file),
|
||||
Err(e) => {
|
||||
panic!(e);
|
||||
}
|
||||
};
|
||||
|
||||
for rline in file.lines() {
|
||||
let line = rline.unwrap();
|
||||
if line == "" || line.starts_with("#") {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut parts = line.split_whitespace();
|
||||
|
||||
let key = parts.next().unwrap();
|
||||
|
||||
if parts.next().unwrap() != "=" {
|
||||
panic!("malformatted line in config: {}", line);
|
||||
}
|
||||
|
||||
let val = parts.next().unwrap().to_string();
|
||||
|
||||
match key {
|
||||
"default_host" => config.set_default_host(val),
|
||||
"gem_root" => config.set_gem_root(val),
|
||||
"listen" => config.add_addr(val),
|
||||
"user" => config.set_user(val),
|
||||
"group" => config.set_group(val),
|
||||
"cert_key" => config.set_cert_key(val),
|
||||
"cert_chain" => config.set_cert_chain(val),
|
||||
_ => {
|
||||
panic!("unknown key in config: {}", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(config)
|
||||
return config;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let config = match parse_args() {
|
||||
Some(config) => config,
|
||||
Some(config_fname) => parse_config(config_fname),
|
||||
None => {
|
||||
help();
|
||||
return;
|
||||
|
|
|
@ -17,6 +17,8 @@ pub struct ServerConfig {
|
|||
addrs: Vec<SocketAddr>,
|
||||
user: unistd::Uid,
|
||||
group: unistd::Gid,
|
||||
cert_key: String,
|
||||
cert_chain: String,
|
||||
}
|
||||
|
||||
impl ServerConfig {
|
||||
|
@ -27,6 +29,8 @@ impl ServerConfig {
|
|||
addrs: Vec::new(),
|
||||
user: unistd::getuid(),
|
||||
group: unistd::getgid(),
|
||||
cert_key: "".to_string(),
|
||||
cert_chain: "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,17 +57,31 @@ impl ServerConfig {
|
|||
|
||||
pub fn set_user(&mut self, uname: String) {
|
||||
self.user = match unistd::User::from_name(&uname) {
|
||||
Ok(user) => user.unwrap().uid,
|
||||
Ok(user) => match user {
|
||||
Some(user) => user.uid,
|
||||
None => panic!("unknown user {}", uname),
|
||||
},
|
||||
Err(e) => panic!(e),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set_group(&mut self, gname: String) {
|
||||
self.group = match unistd::Group::from_name(&gname) {
|
||||
Ok(group) => group.unwrap().gid,
|
||||
Ok(group) => match group {
|
||||
Some(group) => group.gid,
|
||||
None => panic!("unknown group {}", gname),
|
||||
},
|
||||
Err(e) => panic!(e),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set_cert_key(&mut self, fname: String) {
|
||||
self.cert_key = fname;
|
||||
}
|
||||
|
||||
pub fn set_cert_chain(&mut self, fname: String) {
|
||||
self.cert_chain = fname;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Server {
|
||||
|
@ -77,18 +95,20 @@ impl Server {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_acceptor() -> std::sync::Arc<SslAcceptor> {
|
||||
fn build_acceptor(config: &ServerConfig) -> std::sync::Arc<SslAcceptor> {
|
||||
let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
|
||||
acceptor
|
||||
.set_private_key_file("doc/key.pem", SslFiletype::PEM)
|
||||
.set_private_key_file(config.cert_key.as_str(), SslFiletype::PEM)
|
||||
.unwrap();
|
||||
acceptor
|
||||
.set_certificate_chain_file(config.cert_chain.as_str())
|
||||
.unwrap();
|
||||
acceptor.set_certificate_chain_file("doc/cert.pem").unwrap();
|
||||
acceptor.check_private_key().unwrap();
|
||||
return Arc::new(acceptor.build());
|
||||
}
|
||||
|
||||
pub fn serve(&self) {
|
||||
let acceptor = Server::build_acceptor();
|
||||
let acceptor = Server::build_acceptor(&self.config);
|
||||
let listener = TcpListener::bind(&self.config.addrs[..]).unwrap();
|
||||
|
||||
if self.config.user.is_root() {
|
||||
|
|
Loading…
Reference in a new issue