From 12b1cf392315c6a56d22c83680a4f07e25e86679 Mon Sep 17 00:00:00 2001 From: int 80h Date: Tue, 26 May 2020 16:59:06 -0400 Subject: [PATCH] Added CGI vars AUTH_TYPE, REMOTE_USER and TLS_CLIENT_HASH --- Cargo.toml | 2 +- README | 6 ++++++ src/cgi.rs | 28 +++++++++++++++++++++++++--- src/main.rs | 1 + src/tls.rs | 12 ++++++++++-- src/util.rs | 12 ++++++++++++ 6 files changed, 55 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 213d57a..75b46db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gemserv" -version = "0.4.2" +version = "0.4.3" authors = ["int 80h "] edition = "2018" diff --git a/README b/README index d00b22b..7cdf927 100644 --- a/README +++ b/README @@ -69,3 +69,9 @@ config file under "cgienv" - REMOTE_PORT - QUERY_STRING - PATH_INFO + +TLS variables + - AUTH_TYPE + - TLS_CLIENT_HASH + - REMOTE_USER + diff --git a/src/cgi.rs b/src/cgi.rs index f4175fa..a5dd900 100644 --- a/src/cgi.rs +++ b/src/cgi.rs @@ -19,9 +19,10 @@ use crate::config; use crate::conn; use crate::logger; use crate::status::Status; +use crate::util; #[cfg(any(feature = "cgi", feature = "scgi"))] -fn envs(peer_addr: SocketAddr, srv: &config::ServerCfg, url: &url::Url) -> HashMap { +fn envs(peer_addr: SocketAddr, x509: Option, srv: &config::ServerCfg, url: &url::Url) -> HashMap { let mut envs = HashMap::new(); envs.insert("GATEWAY_INTERFACE".to_string(), "CGI/1.1".to_string()); envs.insert("GEMINI_URL".to_string(), url.to_string()); @@ -38,6 +39,24 @@ fn envs(peer_addr: SocketAddr, srv: &config::ServerCfg, url: &url::Url) -> HashM envs.insert("QUERY_STRING".to_string(), q.to_string()); } + match x509 { + Some(x) => { + envs.insert("AUTH_TYPE".to_string(), "Certificate".to_string()); + + let cn = x.subject_name().entries_by_nid(openssl::nid::Nid::COMMONNAME); + for c in cn { + let cd = match c.data().as_utf8() { + Ok(n) => n.to_string(), + _ => "".to_string(), + }; + envs.insert("REMOTE_USER".to_string(), cd); + } + + envs.insert("TLS_CLIENT_HASH".to_string(), util::fingerhex(&x)); + }, + None => {}, + } + match &srv.server.cgienv { Some(c) => { for (k, v) in c.iter() { @@ -76,7 +95,9 @@ pub async fn cgi( script_name: String, path_info: String ) -> Result<(), io::Error> { - let mut envs = envs(con.peer_addr, srv, &url); + + let x509 = con.stream.ssl().peer_certificate(); + let mut envs = envs(con.peer_addr, x509, srv, &url); envs.insert("SCRIPT_NAME".into(), script_name); envs.insert("PATH_INFO".into(), path_info); @@ -141,7 +162,8 @@ pub async fn scgi(addr: String, u: url::Url, mut con: conn::Connection, srv: &co return Ok(()); } }; - let envs = envs(con.peer_addr, srv, &u); + let x509 = con.stream.ssl().peer_certificate(); + let envs = envs(con.peer_addr, x509, srv, &u); let len = 0usize; let mut byt = String::from(format!("CONTENT_LENGTH\x00{}\x00SCGI\x001\x00 RQUEST_METHOD\x00POST\x00REQUEST_URI\x00{}\x00", len, u.path())); diff --git a/src/main.rs b/src/main.rs index 6363147..995ef13 100644 --- a/src/main.rs +++ b/src/main.rs @@ -432,6 +432,7 @@ fn main() -> io::Result<()> { return Ok(()); }, }; + let srv = match stream.ssl().servername(NameType::HOST_NAME) { Some(s) => match cmap.get(s) { Some(ss) => ss, diff --git a/src/tls.rs b/src/tls.rs index 7d352fc..e778d30 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -7,17 +7,19 @@ use openssl::ssl::NameType; use openssl::ssl::SniError; use openssl::ssl::SslContextBuilder; use openssl::ssl::SslVersion; +use openssl::ssl::SslVerifyMode; use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; use crate::config; pub fn acceptor_conf(cfg: config::Config) -> Result { - let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls())?; + let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls_server())?; acceptor.set_min_proto_version(Some(SslVersion::TLS1_2))?; let mut map = HashMap::new(); let mut num = 1; for server in cfg.server.iter() { - let mut ctx = SslContextBuilder::new(SslMethod::tls())?; + let mut ctx = SslContextBuilder::new(SslMethod::tls_server())?; + ctx.set_verify(SslVerifyMode::NONE); match ctx.set_private_key_file(&server.key, SslFiletype::PEM) { Ok(c) => c, Err(e) => { @@ -55,7 +57,13 @@ pub fn acceptor_conf(cfg: config::Config) -> Result { } }) .expect("Can't get sni"); + // for client certs we don't have anything to verify right now? + ssl.set_verify_callback(SslVerifyMode::PEER, |_ver, _store| -> bool { + return true + }); + Ok(()) }); + Ok(acceptor.build()) } diff --git a/src/util.rs b/src/util.rs index c215ad1..e3a1061 100644 --- a/src/util.rs +++ b/src/util.rs @@ -6,3 +6,15 @@ pub fn url_decode(url: &[u8]) -> String { .collect(); return decoded } + +pub fn fingerhex(x509: &openssl::x509::X509) -> String { + let finger = match x509.digest(openssl::hash::MessageDigest::sha256()) { + Ok(f) => f, + _ => return "".to_string(), + }; + let mut hex: String = String::from("SHA256:"); + for f in finger.as_ref() { + hex.push_str(&format!("{:02X}", f)); + } + hex +}