~klve/poptea

3cf38e5834ca5eed278546f191ca0dfd67dbfdae — klve bunc ntnn 6 months ago b236b4f
WIP of tls client extraction from main to lib
4 files changed, 90 insertions(+), 11 deletions(-)

M src/bin/poptea-cli.rs
A src/infra/client.rs
A src/infra/mod.rs
M src/lib.rs
M src/bin/poptea-cli.rs => src/bin/poptea-cli.rs +9 -6
@@ 1,6 1,6 @@
use std::sync::Arc;
use io::{Read, Write};
use std::io;
use std::sync::Arc;

fn main() {
    let root_store = rustls::RootCertStore::empty();


@@ 8,15 8,19 @@ fn main() {
        .with_safe_defaults()
        .with_root_certificates(root_store)
        .with_no_client_auth();
    config.dangerous()
        .set_certificate_verifier(Arc::new(NoCertificateVerification{}));
    config
        .dangerous()
        .set_certificate_verifier(Arc::new(NoCertificateVerification {}));
    let arc = std::sync::Arc::new(config);

    let mut sess = rustls::ClientConnection::new(arc, "transjovian.org".try_into().unwrap()).unwrap();
    let mut sess =
        rustls::ClientConnection::new(arc, "transjovian.org".try_into().unwrap()).unwrap();
    let mut sock = std::net::TcpStream::connect("transjovian.org:1965").unwrap();
    let mut stream = rustls::Stream::new(&mut sess, &mut sock);

    stream.write_all(b"gemini://transjovian.org/oracle/\r\n").unwrap();
    stream
        .write_all(b"gemini://transjovian.org/oracle/\r\n")
        .unwrap();
    let mut plaintext = Vec::new();
    stream.read_to_end(&mut plaintext).unwrap();
    io::stdout().write_all(&plaintext).unwrap();


@@ 37,4 41,3 @@ impl rustls::client::ServerCertVerifier for NoCertificateVerification {
        Ok(rustls::client::ServerCertVerified::assertion())
    }
}


A src/infra/client.rs => src/infra/client.rs +70 -0
@@ 0,0 1,70 @@
use std::net::TcpStream;

use io::{Read, Write};
use std::io;
use std::sync::Arc;
use rustls::ClientConnection;

use crate::{PopResult, GemResponse, GeminiClient};

struct NoCertificateVerification {}

impl rustls::client::ServerCertVerifier for NoCertificateVerification {
    fn verify_server_cert(
        &self,
        _end_entity: &rustls::Certificate,
        _intermediates: &[rustls::Certificate],
        _server_name: &rustls::ServerName,
        _scts: &mut dyn Iterator<Item = &[u8]>,
        _ocsp: &[u8],
        _now: std::time::SystemTime,
    ) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
        Ok(rustls::client::ServerCertVerified::assertion())
    }
}

struct TlsClient {
    socket: TcpStream,
    closing: bool,
    clean_closure: bool,
    tls_conn: rustls::ClientConnection,
}

impl TlsClient {
    fn new(
        sock: TcpStream,
        server_name: rustls::ServerName,
        cfg: Arc<rustls::ClientConfig>,
    ) -> Self {
        Self {
            socket: sock,
            closing: false,
            clean_closure: false,
            tls_conn: ClientConnection::new(cfg, server_name).unwrap(),
        }
    }

    fn get_stream(&self, url: &str) -> PopResult<rustls::Stream<ClientConnection, TcpStream>> {
        let root_store = rustls::RootCertStore::empty();
        let mut config = rustls::ClientConfig::builder()
            .with_safe_defaults()
            .with_root_certificates(root_store)
            .with_no_client_auth();
        config
            .dangerous()
            .set_certificate_verifier(Arc::new(NoCertificateVerification {}));
        let arc = std::sync::Arc::new(config);

        let mut sess =
            rustls::ClientConnection::new(arc, "transjovian.org".try_into().unwrap()).unwrap();
        let mut sock = std::net::TcpStream::connect("transjovian.org:1965").unwrap();
        let mut stream = rustls::Stream::new(&mut sess, &mut sock);
        Ok(stream)
    }
}

impl GeminiClient for TlsClient {
    fn get(&self, url: &str) -> PopResult<GemResponse> {
        unimplemented!()
    }
}

A src/infra/mod.rs => src/infra/mod.rs +3 -0
@@ 0,0 1,3 @@
mod client;

pub use client::RustlsClient;

M src/lib.rs => src/lib.rs +8 -5
@@ 1,3 1,5 @@
mod infra;

enum GemStatus {
    Input,
    SensitiveInput,


@@ 29,12 31,13 @@ struct GemResponse {
    body: Option<String>,
}

enum GemError {
    Local(String),
    Remote(String),
trait GeminiClient {
    fn get(&self, url: &str) -> PopResult<GemResponse>;
}

trait GeminiClient {
    fn get(&self, url: &str) -> Result<GemResponse, GemError>;
enum PopError {
    Local(String),
    Remote(String),
}

pub type PopResult<T> = Result<T, PopError>;