Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the user certificates as additional certificates to the ClientBuilder #2392

Merged

Conversation

poljar
Copy link
Contributor

@poljar poljar commented Feb 14, 2024

Now, this is a story all about how
Certificates work in Android town
And I'd like to take a minute
Enter, close the door
I'll tell you how I've figured out the inner workings of the Keystore

Well it all boils down to the fact that Google got scared
It said, "Your certs are movin' to a place you'll never find 'em".

So the directory, user certificates are stored, is hard to find, and possibly not readable by your application[1]. Instead, we need to use the Keystore[2] API, specifically we'll need to open the AndroidCAStore Keystore type.

The various Keystore types are supposedly documented[3], but I'm failing to find a logical path that would lead you to conclude that:

  1. System certificates can or should be accessed using the Keystore, specifically the AndroidCAStore type
  2. User certificates can be found in the same Keystore type as the system certificates

So this was mostly found using random googling, swearing, and a couple of educated guesses.

Type of change

  • Feature
  • Bugfix
  • Technical
  • Other :

Content

The Rust SDK, if configured to use the rustls crate for SSL reads the system certificates using the openssl-probe crate. The openssl-probe crate reads the certificates from some predefined directory. This directory doesn't contain any additional certificates the user installed on the device.

Like previously mentioned, user-installed certificates should™ be gathered via the Keystore API and that one might not be available from Rust land. We can't easily modify the openssl-probe to use the Keystore API so here we are doing it the dumb way. We load the certs from the Kotlin side and push them to the Rust side.

It would probably be nice to write a test for the method that gathers the certificates, but I have no idea how to do this.

This PR requires: matrix-org/matrix-rust-sdk#3126

Motivation and context

Sorry, no motivation was found. Somebody told me to do this.

Screenshots / GIFs

mitmproxy.webm

Tests

  • Generate a fresh set of self-signed certificates using mitmproxy, mitmproxy does this automatically when it starts up the first time.
  • Push the mitmproxy certificate to the emulated device using adb push mitmproxy-ca-cert.cer /data/local
  • Install the certificate as a user certificate under Security & privacy => More security settings => Encryption & credentials
  • Run mitmproxy in reverse proxy mode mitmproxy --mode reverse:http://localhost:8008 -k --listen-port 8010
  • Forward the 8010 port through adb adb reverse tcp:8010 tcp:8010
  • Try to connect to the mitmproxy reverse proxy using https://localhost:8010 as the homeserver address

Tested devices

  • Physical
  • Emulator
  • OS version(s):

Android 14.0 ("UpsideDownCake") | x86_64 | API 34

Checklist

@poljar poljar requested a review from a team as a code owner February 14, 2024 13:39
@poljar poljar requested review from bmarty and removed request for a team February 14, 2024 13:39
Copy link
Contributor

Thank you for your contribution! Here are a few things to check in the PR to ensure it's reviewed as quickly as possible:

  • Your branch should be based on origin/develop, at least when it was created.
  • There is a changelog entry in the changelog.d folder with the Towncrier format.
  • The test pass locally running ./gradlew test.
  • The code quality check suite pass locally running ./gradlew runQualityChecks.
  • If you modified anything related to the UI, including previews, you'll have to run the Record screenshots GH action in your forked repo: that will generate compatible new screenshots. However, given Github Actions limitations, it will prevent the CI from running temporarily, until you upload a new commit after that one. To do so, just pull the latest changes and push an empty commit.

…lder

Now, this is a story all about how
Certificates work in Android town
And I'd like to take a minute
Enter, close the door
I'll tell you how I've figured out the inner workings of the Keystore

Well it all boils down the fact that Google got scared
It said, "You're certs are movin' to a place you won't find".

So the directory, user certificates are stored, is hard to find, and possibly
not readable by your application[1]. Instead, we need to use the Keystore[2]
API, specifically we'll need to open the `AndroidCAStore` Keystore type.

The various Keystore types are supposedly documented[3], but I'm failing to
find a logical path that would lead you to conclude that:

    a) System certificates can or should be accessed using the Keystore,
       specifically the AndroidCAStore type
    b) User certificates can be found in the same Keystore type as the system
       certificates

So this was mostly found using random googling, swearing, and a couple of
educated guesses.

[1]: https://android-developers.googleblog.com/2016/07/changes-to-trusted-certificate.html
[2]: https://developer.android.com/reference/java/security/KeyStore
[3]: https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html#keystore-types
@poljar
Copy link
Contributor Author

poljar commented Feb 21, 2024

What do I need to do to get this merged/reviewed? The CI failures seem to be caused by the fact that I created the PR from a fork and a random 500 error codecov threw.

In other words, the CI failures are unrelated to the changes I made.

@jmartinesp
Copy link
Contributor

I tried to test this, but I can't get anything in mitmproxy, probably because the OkHttp request we do to https://localhost:8081 fails before the Rust SDK can do anything. What did you do to have the results seen in the video?

@bmarty bmarty changed the base branch from develop to feature/bma/userCertificates February 22, 2024 09:50
@bmarty
Copy link
Member

bmarty commented Feb 22, 2024

Thanks @poljar, I will merge the PR in a branch I own to be able to add more commit. This will then be reviewed as a regular PR.

@bmarty bmarty merged commit 1751920 into element-hq:feature/bma/userCertificates Feb 22, 2024
9 of 11 checks passed
@poljar
Copy link
Contributor Author

poljar commented Feb 22, 2024

I tried to test this, but I can't get anything in mitmproxy, probably because the OkHttp request we do to https://localhost:8081 fails before the Rust SDK can do anything. What did you do to have the results seen in the video?

I think that this is due to Synapse not being reachable, you can use matrix.org to test this if you don't have a local Synapse running:

mitmproxy --mode reverse:https://matrix.org --listen-port 8010

Just note that once well-known has been handled, after logging in, the reverse proxy won't be used by the Client anymore.

@jmartinesp
Copy link
Contributor

I think that this is due to Synapse not being reachable, you can use matrix.org to test this if you don't have a local Synapse running:

mitmproxy --mode reverse:https://matrix.org --listen-port 8010

Just note that once well-known has been handled, after logging in, the reverse proxy won't be used by the Client anymore.

I can confirm it works as expected when using matrix.org, it's a problem with my local setup. Thanks again for the help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants