ffi: Expose the method to add additional certs in the bindings

This commit is contained in:
Damir Jelić
2024-02-14 09:57:34 +01:00
parent 7e61a6dd31
commit 32afc56005
2 changed files with 46 additions and 1 deletions

View File

@@ -26,7 +26,11 @@ use url::Url;
use zeroize::Zeroize;
use super::{client::Client, client_builder::ClientBuilder, RUNTIME};
use crate::{client::ClientSessionDelegate, client_builder::UrlScheme, error::ClientError};
use crate::{
client::ClientSessionDelegate,
client_builder::{CertificateBytes, UrlScheme},
error::ClientError,
};
#[derive(uniffi::Object)]
pub struct AuthenticationService {
@@ -39,6 +43,7 @@ pub struct AuthenticationService {
custom_sliding_sync_proxy: RwLock<Option<String>>,
cross_process_refresh_lock_id: Option<String>,
session_delegate: Option<Arc<dyn ClientSessionDelegate>>,
additional_root_certificates: Vec<CertificateBytes>,
}
impl Drop for AuthenticationService {
@@ -176,10 +181,15 @@ impl HomeserverLoginDetails {
impl AuthenticationService {
/// Creates a new service to authenticate a user with.
#[uniffi::constructor]
// TODO: This has too many arguments, even clippy agrees. Many of these methods are the same as
// for the `ClientBuilder`. We should let people pass in a `ClientBuilder` and possibly convert
// this to a builder pattern as well.
#[allow(clippy::too_many_arguments)]
pub fn new(
base_path: String,
passphrase: Option<String>,
user_agent: Option<String>,
additional_root_certificates: Vec<Vec<u8>>,
oidc_configuration: Option<OidcConfiguration>,
custom_sliding_sync_proxy: Option<String>,
session_delegate: Option<Box<dyn ClientSessionDelegate>>,
@@ -195,6 +205,7 @@ impl AuthenticationService {
custom_sliding_sync_proxy: RwLock::new(custom_sliding_sync_proxy),
session_delegate: session_delegate.map(Into::into),
cross_process_refresh_lock_id,
additional_root_certificates,
})
}
@@ -385,6 +396,8 @@ impl AuthenticationService {
builder = builder.user_agent(user_agent);
}
builder = builder.add_root_certificates(self.additional_root_certificates.clone());
builder
}

View File

@@ -2,6 +2,7 @@ use std::{fs, path::PathBuf, sync::Arc};
use matrix_sdk::{
encryption::{BackupDownloadStrategy, EncryptionSettings},
reqwest::Certificate,
ruma::{
api::{error::UnknownVersionError, MatrixVersion},
ServerName, UserId,
@@ -15,6 +16,9 @@ use zeroize::Zeroizing;
use super::{client::Client, RUNTIME};
use crate::{client::ClientSessionDelegate, error::ClientError, helpers::unwrap_or_clone_arc};
/// A list of bytes containing a certificate in DER or PEM form.
pub type CertificateBytes = Vec<u8>;
#[derive(Clone)]
pub(crate) enum UrlScheme {
Http,
@@ -37,6 +41,7 @@ pub struct ClientBuilder {
inner: MatrixClientBuilder,
cross_process_refresh_lock_id: Option<String>,
session_delegate: Option<Arc<dyn ClientSessionDelegate>>,
additional_root_certificates: Vec<Vec<u8>>,
}
#[uniffi::export]
@@ -62,6 +67,7 @@ impl ClientBuilder {
}),
cross_process_refresh_lock_id: None,
session_delegate: None,
additional_root_certificates: Default::default(),
})
}
@@ -149,6 +155,16 @@ impl ClientBuilder {
Arc::new(builder)
}
pub fn add_root_certificates(
self: Arc<Self>,
certificates: Vec<CertificateBytes>,
) -> Arc<Self> {
let mut builder = unwrap_or_clone_arc(self);
builder.additional_root_certificates = certificates;
Arc::new(builder)
}
pub fn build(self: Arc<Self>) -> Result<Arc<Client>, ClientError> {
Ok(Arc::new(self.build_inner()?))
}
@@ -224,6 +240,22 @@ impl ClientBuilder {
);
}
let mut certificates = Vec::new();
for certificate in builder.additional_root_certificates {
// We don't really know what type of certificate we may get here, so let's try
// first one type, then the other.
if let Ok(cert) = Certificate::from_der(&certificate) {
certificates.push(cert);
} else {
let cert = Certificate::from_pem(&certificate)
.map_err(|e| anyhow::anyhow!("Failed to add a root certificate {e:?}"))?;
certificates.push(cert);
}
}
inner_builder = inner_builder.add_root_certificates(certificates);
if let Some(proxy) = builder.proxy {
inner_builder = inner_builder.proxy(proxy);
}