fix guest certificate session cast

This commit is contained in:
yggverse 2024-12-01 09:15:53 +02:00
parent 8b6f2200f5
commit e442a2880a

View file

@ -15,7 +15,7 @@ use glib::{
pub struct Connection { pub struct Connection {
pub socket_connection: SocketConnection, pub socket_connection: SocketConnection,
pub tls_client_connection: TlsClientConnection, pub tls_client_connection: Option<TlsClientConnection>,
} }
impl Connection { impl Connection {
@ -28,30 +28,17 @@ impl Connection {
server_identity: Option<NetworkAddress>, server_identity: Option<NetworkAddress>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
Ok(Self { Ok(Self {
tls_client_connection: match TlsClientConnection::new( tls_client_connection: match certificate {
&socket_connection, Some(ref certificate) => {
server_identity.as_ref(), match new_tls_client_connection(&socket_connection, server_identity.as_ref()) {
) { Ok(tls_client_connection) => {
Ok(tls_client_connection) => { tls_client_connection.set_certificate(certificate);
// Prevent session resumption (on certificate change in runtime) Some(tls_client_connection)
tls_client_connection.set_property("session-resumption-enabled", false); }
Err(e) => return Err(e),
// Is user session
// https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates
if let Some(ref certificate) = certificate {
tls_client_connection.set_certificate(certificate);
} }
// @TODO handle
// https://geminiprotocol.net/docs/protocol-specification.gmi#closing-connections
tls_client_connection.set_require_close_notify(true);
// @TODO validate
// https://geminiprotocol.net/docs/protocol-specification.gmi#tls-server-certificate-validation
tls_client_connection.connect_accept_certificate(|_, _, _| true);
tls_client_connection
} }
Err(e) => return Err(Error::TlsClientConnection(e)), None => None,
}, },
socket_connection, socket_connection,
}) })
@ -68,27 +55,22 @@ impl Connection {
cancellable: Cancellable, cancellable: Cancellable,
callback: impl Fn(Result<Response, Error>) + 'static, callback: impl Fn(Result<Response, Error>) + 'static,
) { ) {
self.tls_client_connection self.stream().output_stream().write_bytes_async(
.output_stream() &Bytes::from(format!("{query}\r\n").as_bytes()),
.write_bytes_async( priority,
&Bytes::from(format!("{query}\r\n").as_bytes()), Some(&cancellable.clone()),
priority, move |result| match result {
Some(&cancellable.clone()), Ok(_) => {
move |result| match result { Response::from_connection_async(self, priority, cancellable, move |result| {
Ok(_) => Response::from_connection_async( callback(match result {
self, Ok(response) => Ok(response),
priority, Err(e) => Err(Error::Response(e)),
cancellable, })
move |result| { })
callback(match result { }
Ok(response) => Ok(response), Err(e) => callback(Err(Error::Stream(e))),
Err(e) => Err(Error::Response(e)), },
}) );
},
),
Err(e) => callback(Err(Error::Stream(e))),
},
);
} }
// Getters // Getters
@ -101,9 +83,35 @@ impl Connection {
pub fn stream(&self) -> impl IsA<IOStream> { pub fn stream(&self) -> impl IsA<IOStream> {
// * do not replace with `tls_client_connection.base_io_stream()` // * do not replace with `tls_client_connection.base_io_stream()`
// as it will not work properly for user certificate sessions! // as it will not work properly for user certificate sessions!
match self.tls_client_connection.certificate().is_some() { match self.tls_client_connection.is_some() {
true => self.tls_client_connection.clone().upcast::<IOStream>(), // is user session true => self
false => self.socket_connection.clone().upcast::<IOStream>(), // is guest session .tls_client_connection
.clone()
.unwrap()
.upcast::<IOStream>(), // is user session
false => self.socket_connection.clone().upcast::<IOStream>(), // is guest session
} }
} }
} }
fn new_tls_client_connection(
socket_connection: &SocketConnection,
server_identity: Option<&NetworkAddress>,
) -> Result<TlsClientConnection, Error> {
match TlsClientConnection::new(socket_connection, server_identity) {
Ok(tls_client_connection) => {
// Prevent session resumption (on certificate change in runtime)
tls_client_connection.set_property("session-resumption-enabled", false);
// @TODO handle
// https://geminiprotocol.net/docs/protocol-specification.gmi#closing-connections
tls_client_connection.set_require_close_notify(true);
// @TODO validate
// https://geminiprotocol.net/docs/protocol-specification.gmi#tls-server-certificate-validation
tls_client_connection.connect_accept_certificate(|_, _, _| true);
Ok(tls_client_connection)
}
Err(e) => Err(Error::TlsClientConnection(e)),
}
}