~boringcactus/gemifedi

b7a127e6bf5065e19f433fa62baf42bb9b64cd81 — Melody Horn 1 year, 30 days ago d393910 v0.3.1
add a horribly insecure mode that doesn't check client certificates
1 files changed, 31 insertions(+), 14 deletions(-)

M src/main.rs
M src/main.rs => src/main.rs +31 -14
@@ 21,6 21,7 @@ use maj::{
    route, split, seg,
};
use rustls::ServerConfig;
use structopt::StructOpt;

mod client_cert_fix;
use client_cert_fix::TrustAnyClientCertOrAnonymous;


@@ 100,7 101,10 @@ fn render_post(post: elefren::entities::status::Status, highlight: bool) -> Vec<
    result
}

fn mastodon_data_path(req: &GeminiRequest) -> Option<PathBuf> {
fn mastodon_data_path(req: &GeminiRequest, handler: &Handler) -> Option<PathBuf> {
    if handler.horribly_insecure {
        return Some(PathBuf::from("data/user.toml"));
    }
    let mut result = PathBuf::from("data");
    result.push("users");
    let hash = req.cert_hash()?;


@@ 108,17 112,21 @@ fn mastodon_data_path(req: &GeminiRequest) -> Option<PathBuf> {
    Some(result.with_extension("toml"))
}

struct Handler;
struct Handler {
    horribly_insecure: bool,
}

impl Default for Handler {
    fn default() -> Self {
        Handler {}
impl Handler {
    fn new(options: &Opt) -> Self {
        Handler {
            horribly_insecure: options.horribly_insecure,
        }
    }
}

impl Handler {
    fn home(&self, req: GeminiRequest) -> Result<GeminiResponse, Error> {
        let path = mastodon_data_path(&req);
        let path = mastodon_data_path(&req, &self);
        let path = match path {
            Some(path) => path,
            None => return Ok(GeminiResponse::need_cert("Need a cert to be able to log in!"))


@@ 148,7 156,7 @@ impl Handler {
    }

    fn post(&self, req: GeminiRequest) -> Result<GeminiResponse, Error> {
        let path = mastodon_data_path(&req);
        let path = mastodon_data_path(&req, &self);
        let path = match path {
            Some(path) => path,
            None => return Ok(GeminiResponse::need_cert("Need a cert to be able to log in!"))


@@ 212,7 220,7 @@ impl Handler {
        let mastodon = app_install.complete(code).unwrap();

        // Save app data for using on the next run.
        let path = mastodon_data_path(&req);
        let path = mastodon_data_path(&req, &self);
        let path = match path {
            Some(path) => path,
            None => return Ok(GeminiResponse::need_cert("Need a cert to be able to log in!"))


@@ 227,7 235,7 @@ impl Handler {
    }

    fn status(&self, req: GeminiRequest, id: &str) -> Result<GeminiResponse, Error> {
        let path = mastodon_data_path(&req);
        let path = mastodon_data_path(&req, &self);
        let path = match path {
            Some(path) => path,
            None => return Ok(GeminiResponse::need_cert("Need a cert to be able to log in!"))


@@ 282,7 290,7 @@ impl Handler {
    }

    fn reply(&self, req: GeminiRequest, id: &str) -> Result<GeminiResponse, Error> {
        let path = mastodon_data_path(&req);
        let path = mastodon_data_path(&req, &self);
        let path = match path {
            Some(path) => path,
            None => return Ok(GeminiResponse::need_cert("Need a cert to be able to log in!"))


@@ 321,7 329,7 @@ gemifedi is a Mastodon / Pleroma client for the Gemini protocol. it uses the OAu
    }

    fn logout(&self, req: GeminiRequest) -> Result<GeminiResponse, Error> {
        let path = mastodon_data_path(&req);
        let path = mastodon_data_path(&req, &self);
        let path = match path {
            Some(path) => path,
            None => return Ok(GeminiResponse::need_cert("Need a cert to be able to log in!"))


@@ 352,8 360,6 @@ impl GeminiHandler for Handler {
    }
}

use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(author, about)]
struct Opt {


@@ 372,6 378,10 @@ struct Opt {
    /// Port number to run on
    #[structopt(default_value = "1965")]
    port: u16,

    /// Don't use client certs and just trust everyone to be you - dangerous, only accepted on localhost
    #[structopt(long)]
    horribly_insecure: bool,
}

#[async_std::main]


@@ 383,11 393,18 @@ async fn main() -> Result<(), Error> {

    let options: Opt = Opt::from_args();

    if options.horribly_insecure && options.domain != "localhost" {
        eprintln!("can't be horribly insecure on anything but localhost");
        return Err("insecure non-localhost unsupported".to_string().into())
    }

    if let Err(error) = url::Host::parse(&options.domain) {
        eprintln!("{:?} is not a valid hostname", options.domain);
        return Err(Box::new(error));
    }

    let handler = Handler::new(&options);

    let key_file = options.key.unwrap_or(PathBuf::from(format!("./{}.key", options.domain)));

    if !key_file.exists() {


@@ 459,7 476,7 @@ async fn main() -> Result<(), Error> {
    log::info!("about to start listening on gemini://{}{}/", options.domain, if options.port == 1965 { format!("") } else { format!(":{}", options.port) });

    maj::server::serve(
        Arc::new(Handler::default()),
        Arc::new(handler),
        tls_config,
        options.domain,
        options.port,