mirror of
https://github.com/YGGverse/ggemini.git
synced 2026-03-31 09:05:45 +00:00
implement optional TOFU validation
This commit is contained in:
parent
bb5b1dfb53
commit
44196608ce
4 changed files with 26 additions and 12 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ggemini"
|
name = "ggemini"
|
||||||
version = "0.18.1"
|
version = "0.19.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,8 @@ fn main() -> ExitCode {
|
||||||
},
|
},
|
||||||
Priority::DEFAULT,
|
Priority::DEFAULT,
|
||||||
Cancellable::new(),
|
Cancellable::new(),
|
||||||
None, // optional `GTlsCertificate`
|
None, // optional auth `GTlsCertificate`
|
||||||
|
None, // optional TOFU `GTlsCertificate` array
|
||||||
|result| match result {
|
|result| match result {
|
||||||
Ok((response, _connection)) => match response {
|
Ok((response, _connection)) => match response {
|
||||||
Response::Success(success) => match success.mime().unwrap().as_str() {
|
Response::Success(success) => match success.mime().unwrap().as_str() {
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ impl Client {
|
||||||
request: Request,
|
request: Request,
|
||||||
priority: Priority,
|
priority: Priority,
|
||||||
cancellable: Cancellable,
|
cancellable: Cancellable,
|
||||||
certificate: Option<TlsCertificate>,
|
client_certificate: Option<TlsCertificate>,
|
||||||
|
server_certificates: Option<Vec<TlsCertificate>>,
|
||||||
callback: impl FnOnce(Result<(Response, Connection), Error>) + 'static,
|
callback: impl FnOnce(Result<(Response, Connection), Error>) + 'static,
|
||||||
) {
|
) {
|
||||||
// Begin new connection
|
// Begin new connection
|
||||||
|
|
@ -75,7 +76,8 @@ impl Client {
|
||||||
match Connection::build(
|
match Connection::build(
|
||||||
socket_connection,
|
socket_connection,
|
||||||
network_address,
|
network_address,
|
||||||
certificate,
|
client_certificate,
|
||||||
|
server_certificates,
|
||||||
is_session_resumption,
|
is_session_resumption,
|
||||||
) {
|
) {
|
||||||
Ok(connection) => connection.request_async(
|
Ok(connection) => connection.request_async(
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,9 @@ pub use error::Error;
|
||||||
pub use request::{Mode, Request};
|
pub use request::{Mode, Request};
|
||||||
pub use response::Response;
|
pub use response::Response;
|
||||||
|
|
||||||
// Local dependencies
|
|
||||||
|
|
||||||
use gio::{
|
use gio::{
|
||||||
Cancellable, IOStream, NetworkAddress, SocketConnection, TlsCertificate, TlsClientConnection,
|
Cancellable, IOStream, NetworkAddress, SocketConnection, TlsCertificate, TlsClientConnection,
|
||||||
prelude::{IOStreamExt, OutputStreamExtManual, TlsConnectionExt},
|
prelude::{IOStreamExt, OutputStreamExtManual, TlsCertificateExt, TlsConnectionExt},
|
||||||
};
|
};
|
||||||
use glib::{
|
use glib::{
|
||||||
Bytes, Priority,
|
Bytes, Priority,
|
||||||
|
|
@ -30,17 +28,19 @@ impl Connection {
|
||||||
pub fn build(
|
pub fn build(
|
||||||
socket_connection: SocketConnection,
|
socket_connection: SocketConnection,
|
||||||
network_address: NetworkAddress,
|
network_address: NetworkAddress,
|
||||||
certificate: Option<TlsCertificate>,
|
client_certificate: Option<TlsCertificate>,
|
||||||
|
server_certificates: Option<Vec<TlsCertificate>>,
|
||||||
is_session_resumption: bool,
|
is_session_resumption: bool,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
tls_client_connection: match new_tls_client_connection(
|
tls_client_connection: match new_tls_client_connection(
|
||||||
&socket_connection,
|
&socket_connection,
|
||||||
Some(&network_address),
|
Some(&network_address),
|
||||||
|
server_certificates,
|
||||||
is_session_resumption,
|
is_session_resumption,
|
||||||
) {
|
) {
|
||||||
Ok(tls_client_connection) => {
|
Ok(tls_client_connection) => {
|
||||||
if let Some(ref c) = certificate {
|
if let Some(ref c) = client_certificate {
|
||||||
tls_client_connection.set_certificate(c);
|
tls_client_connection.set_certificate(c);
|
||||||
}
|
}
|
||||||
tls_client_connection
|
tls_client_connection
|
||||||
|
|
@ -136,6 +136,7 @@ impl Connection {
|
||||||
fn new_tls_client_connection(
|
fn new_tls_client_connection(
|
||||||
socket_connection: &SocketConnection,
|
socket_connection: &SocketConnection,
|
||||||
server_identity: Option<&NetworkAddress>,
|
server_identity: Option<&NetworkAddress>,
|
||||||
|
server_certificates: Option<Vec<TlsCertificate>>,
|
||||||
is_session_resumption: bool,
|
is_session_resumption: bool,
|
||||||
) -> Result<TlsClientConnection, Error> {
|
) -> Result<TlsClientConnection, Error> {
|
||||||
match TlsClientConnection::new(socket_connection, server_identity) {
|
match TlsClientConnection::new(socket_connection, server_identity) {
|
||||||
|
|
@ -149,9 +150,19 @@ fn new_tls_client_connection(
|
||||||
// https://geminiprotocol.net/docs/protocol-specification.gmi#closing-connections
|
// https://geminiprotocol.net/docs/protocol-specification.gmi#closing-connections
|
||||||
tls_client_connection.set_require_close_notify(true);
|
tls_client_connection.set_require_close_notify(true);
|
||||||
|
|
||||||
// @TODO validate
|
// [TOFU](https://geminiprotocol.net/docs/protocol-specification.gmi#tls-server-certificate-validation)
|
||||||
// https://geminiprotocol.net/docs/protocol-specification.gmi#tls-server-certificate-validation
|
tls_client_connection.connect_accept_certificate(move |_, c, _| {
|
||||||
tls_client_connection.connect_accept_certificate(|_, _, _| true);
|
server_certificates
|
||||||
|
.as_ref()
|
||||||
|
.is_none_or(|server_certificates| {
|
||||||
|
for server_certificate in server_certificates {
|
||||||
|
if server_certificate.is_same(c) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
Ok(tls_client_connection)
|
Ok(tls_client_connection)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue