🏗️ Elegant & Highly Performant Async Gemini Server Framework for the Modern Age
async framework gemini-protocol protocol gemini rust
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(router): allow access to client certs

Pretty happy to finally get this one over with...

Fuwn 0736c569 89c872f5

+75 -27
+20 -3
examples/windmark.rs
··· 199 199 ) 200 200 }) 201 201 }); 202 - // router.mount("", Box::new(|_| { 203 - // Response::Success("hi".into()) 204 - // })); 202 + router.mount( 203 + "/secret", 204 + Box::new(|context| { 205 + if let Some(certificate) = context.certificate { 206 + Response::Success(format!("Your public key: {}.", { 207 + (|| -> Result<String, openssl::error::ErrorStack> { 208 + Ok(format!( 209 + "{:?}", 210 + certificate.public_key()?.rsa()?.public_key_to_pem()? 211 + )) 212 + })() 213 + .unwrap_or_else(|_| "Unknown".to_string()) 214 + },)) 215 + } else { 216 + Response::ClientCertificateRequired( 217 + "This is a secret route! Identify yourself!".to_string(), 218 + ) 219 + } 220 + }), 221 + ); 205 222 206 223 router.run().await 207 224 }
+22 -9
src/returnable.rs
··· 17 17 // SPDX-License-Identifier: GPL-3.0-only 18 18 19 19 use matchit::Params; 20 + use openssl::x509::X509; 20 21 use tokio::net::TcpStream; 21 22 use url::Url; 22 23 23 24 pub struct RouteContext<'a> { 24 - pub tcp: &'a TcpStream, 25 - pub url: &'a Url, 26 - pub params: &'a Params<'a, 'a>, 25 + pub tcp: &'a TcpStream, 26 + pub url: &'a Url, 27 + pub params: &'a Params<'a, 'a>, 28 + pub certificate: &'a Option<X509>, 27 29 } 28 30 impl<'a> RouteContext<'a> { 29 31 pub const fn new( 30 32 tcp: &'a TcpStream, 31 33 url: &'a Url, 32 34 params: &'a Params<'a, 'a>, 35 + certificate: &'a Option<X509>, 33 36 ) -> Self { 34 37 Self { 35 38 tcp, 36 39 url, 37 40 params, 41 + certificate, 38 42 } 39 43 } 40 44 } 41 45 42 46 pub struct ErrorContext<'a> { 43 - pub tcp: &'a TcpStream, 44 - pub url: &'a Url, 47 + pub tcp: &'a TcpStream, 48 + pub url: &'a Url, 49 + pub certificate: &'a Option<X509>, 45 50 } 46 51 impl<'a> ErrorContext<'a> { 47 - pub const fn new(tcp: &'a TcpStream, url: &'a Url) -> Self { 52 + pub const fn new( 53 + tcp: &'a TcpStream, 54 + url: &'a Url, 55 + certificate: &'a Option<X509>, 56 + ) -> Self { 48 57 Self { 49 58 tcp, 50 59 url, 60 + certificate, 51 61 } 52 62 } 53 63 } 54 64 55 65 pub struct CallbackContext<'a> { 56 - pub tcp: &'a TcpStream, 57 - pub url: &'a Url, 58 - pub params: Option<&'a Params<'a, 'a>>, 66 + pub tcp: &'a TcpStream, 67 + pub url: &'a Url, 68 + pub params: Option<&'a Params<'a, 'a>>, 69 + pub certificate: &'a Option<X509>, 59 70 } 60 71 impl<'a> CallbackContext<'a> { 61 72 pub const fn new( 62 73 tcp: &'a TcpStream, 63 74 url: &'a Url, 64 75 params: Option<&'a Params<'a, 'a>>, 76 + certificate: &'a Option<X509>, 65 77 ) -> Self { 66 78 Self { 67 79 tcp, 68 80 url, 69 81 params, 82 + certificate, 70 83 } 71 84 } 72 85 }
+33 -15
src/router.rs
··· 299 299 let route = &mut self.routes.at(&fixed_path); 300 300 301 301 for module in &mut *self.modules.lock().unwrap() { 302 - module.on_pre_route(CallbackContext::new(stream.get_ref(), &url, { 303 - if let Ok(route) = &route { 304 - Some(&route.params) 305 - } else { 306 - None 307 - } 308 - })); 302 + module.on_pre_route(CallbackContext::new( 303 + stream.get_ref(), 304 + &url, 305 + { 306 + if let Ok(route) = &route { 307 + Some(&route.params) 308 + } else { 309 + None 310 + } 311 + }, 312 + &stream.ssl().peer_certificate(), 313 + )); 309 314 } 310 315 311 316 (*self.pre_route_callback).lock().unwrap().call_mut(( ··· 330 335 stream.get_ref(), 331 336 &url, 332 337 &route.params, 338 + &stream.ssl().peer_certificate() 333 339 )), 334 340 )); 335 341 } ··· 342 348 stream.get_ref(), 343 349 &url, 344 350 &route.params, 351 + &stream.ssl().peer_certificate() 345 352 )), 346 353 if footers_length > 1 && i != footers_length - 1 { 347 354 "\n" ··· 355 362 stream.get_ref(), 356 363 &url, 357 364 &route.params, 365 + &stream.ssl().peer_certificate(), 358 366 ),)), 359 367 &mut response_status, 360 368 #[cfg(not(feature = "auto-deduce-mime"))] ··· 365 373 (*self.error_handler) 366 374 .lock() 367 375 .unwrap() 368 - .call_mut((ErrorContext::new(stream.get_ref(), &url),)), 376 + .call_mut((ErrorContext::new( 377 + stream.get_ref(), 378 + &url, 379 + &stream.ssl().peer_certificate(), 380 + ),)), 369 381 &mut response_status, 370 382 #[cfg(not(feature = "auto-deduce-mime"))] 371 383 &mut response_mime_type, ··· 404 416 .await?; 405 417 406 418 for module in &mut *self.modules.lock().unwrap() { 407 - module.on_post_route(CallbackContext::new(stream.get_ref(), &url, { 408 - if let Ok(route) = &route { 409 - Some(&route.params) 410 - } else { 411 - None 412 - } 413 - })); 419 + module.on_post_route(CallbackContext::new( 420 + stream.get_ref(), 421 + &url, 422 + { 423 + if let Ok(route) = &route { 424 + Some(&route.params) 425 + } else { 426 + None 427 + } 428 + }, 429 + &stream.ssl().peer_certificate(), 430 + )); 414 431 } 415 432 416 433 (*self.post_route_callback).lock().unwrap().call_mut(( ··· 439 456 )?; 440 457 builder.set_certificate_file(&self.ca_file_name, ssl::SslFiletype::PEM)?; 441 458 builder.check_private_key()?; 459 + builder.set_verify_callback(ssl::SslVerifyMode::PEER, |_, _| true); 442 460 443 461 self.ssl_acceptor = Arc::new(builder.build()); 444 462