-
Notifications
You must be signed in to change notification settings - Fork 92
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
Issue #276 - Support for TLS client certificates #1048
Conversation
SSLContext sslContext = getSSLContext(); | ||
sslContext.init(null, tms, null); | ||
sslContext.init(kms, tms, null); |
Check failure
Code scanning / CodeQL
`TrustManager` that accepts all certificates High
TrustManager
AdvancedX509TrustManager
|
||
val sslContext = NetworkUtils.getSSLContext() | ||
|
||
sslContext.init(null, arrayOf<TrustManager>(trustManager), null) | ||
sslContext.init(arrayOf(keyManager), arrayOf<TrustManager>(trustManager), null) |
Check failure
Code scanning / CodeQL
`TrustManager` that accepts all certificates High
TrustManager
AdvancedX509TrustManager
|
||
val sslContext = NetworkUtils.getSSLContext() | ||
|
||
sslContext.init(null, arrayOf<TrustManager>(trustManager), null) | ||
sslContext.init(arrayOf(keyManager), arrayOf<TrustManager>(trustManager), null) |
Check failure
Code scanning / CodeQL
`TrustManager` that accepts all certificates High
TrustManager
AdvancedX509TrustManager
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I tested your commits but a found an error. The error is that if you use apps in nextcloud like OpenOffice, it will fail to connect with http status error -1. Client cert not selected. The client certificate selector only works for the app it self and not the nextcloud apps inside the instantance of the nextcloud website in the app.
Hi @kushmittal2009, thanks a lot for testing! I am not sure, I understand your testcase correctly. You say:
By "app" do you refer to an app on your Android device or an app in your nextcloud instance? My changes here will only apply, if the client app also makes use of the new In the meantime I prepared a PR to the nextcloud android app as well (PR #11314), which shows what a client app using the android-library has to do to add TLS client support. If that was what you already tested, please let me know how I can reproduce the error, so I can fix it. I am using the nextcloud app with my modifications to the android-library for about two weeks now and so far it works without any trouble. But maybe I missed a usecase. |
Hi @Elv1zz , What I meant was, I tested your commits with the advancedX509keyManager and the compiled nextcloud app does seem to ask for certificate, sign in, and get the home screen of the app. However if you of apps like openoffice installed in your nextcloud server and you click a .doc file, in the logcat is says Client certificate not selected and the nextcloud app gets stuck showing a reload icon on the middle of the screen. The main issue is that if a WebView opens inside of a WebView, the other WebView can not use the saved CLient Certificate with the previous WebView. |
Hi @kushmittal2009, thanks for your detailed explanation! In fact you found an error in my implementation 👍 I implemented the TLS client certificate handling in a sub-class of |
Tests are failing.
|
For some reason I missed the notification about your comment. I will have time to look into this again probably next week.
The |
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #1048 +/- ##
============================================
- Coverage 52.56% 50.47% -2.10%
- Complexity 978 984 +6
============================================
Files 192 191 -1
Lines 7098 7327 +229
Branches 934 958 +24
============================================
- Hits 3731 3698 -33
- Misses 2851 3114 +263
+ Partials 516 515 -1
|
These errors are just in the tests, right? So it can this already be used? |
I am using my fork for quite a while now. So you should be able to use it, yes. And indeed it would be good to have more people using it so find any further potential bugs :) So far there is one known issue left with the branding feature of Nextcloud, for which I hope to find time to look into soon. |
80f35a3
to
901fc9b
Compare
This adds the new `AdvancedX509KeyManager`, which is used to select, manage, and apply a TLS client certificate to establish a secure connection to a server. It includes an interactive component to allow the user to select the client certificate from the device's store. The implementation is based on [`InteractiveKeyManager` by Stephan Ritscher](https://github.com/stephanritscher/InteractiveKeyManager) and was updated, modified, and integrated into the `nextcloud-android-library` by [Elv1zz](https://github.com/Elv1zz). Signed-off-by: Elv1zz <[email protected]>
During code review it was found that HTTP status 400 was only handled in `WebviewClient` based connections, but most connections are using `NextcloudClient`. So if a connection error occurs, most likely because of an expired certificate, it would not be handled correctly, and we would go on trying to use the expired certificate. So now a asic error handling was added. However, so far I did not find a way to handle this kind of error in `OwnCloudClient` due to missing `Context`. Signed-off-by: Elv1zz <[email protected]>
In case server returns an HTTP status code `400` (bad request), we remove the selected TLS client certificate for the corresponding host and port, since it might have expired or be rejected for another reason. For this, the `OwnCloudClient` constructor got an additional `Context` parameter and the class an additional field, since the `Context` is required to construct a new `AdvancedX509KeyManager`. Signed-off-by: Elv1zz <[email protected]>
Instead of using the magic number `400` for the HTTP status code which causes us to drop the selected TLS client certificate, the corresponding named constant from `HttpStatus` is used. Signed-off-by: Elv1zz <[email protected]>
Some replacements of `InteractiveKeyManager` to `AdvancedX509KeyManager` were missed. This was now fixed. Signed-off-by: Elv1zz <[email protected]>
While testing the TLS client certificate implementation I found that most `port`/`getPort` implementations returned `-1` when there was no port defined explicitly in the URL (e.g. `https://localhost/` instead of `https://localhost:443/`). This would lead to keys not being correctly removed. To fix this and making the usage of `removeKeys` more robust and simple, the `removeKeys(host, port)` method was made private, and several overloads were added, which accept all ways of representing an URL found in Nextcloud (and one extra way, which is not used (so far) accepting an `java.net.URI`). They all boil down to a `java.net.URL` which also returns `-1` for an implicit port, but provides the `getDefaultPort` for that case, allowing to get the protocols default port. Signed-off-by: Elv1zz <[email protected]>
To send notifications, we need the corresponding permission, so we have to add it to the `AndroidManifest.xml`. Signed-off-by: Elv1zz <[email protected]>
Before sending a notification, check if the required permission is granted. If it's not granted, we cannot request it, since we do not have an Actvity as that's the only time we try to send notifications. Signed-off-by: Elv1zz <[email protected]>
Forgot to update `NextcloudClient` creation to extended constructor signature, which also requires a `Context` instance. Signed-off-by: Elv1zz <[email protected]>
We try to get the application context from the `Context` instance passed to `AdvancedX509KeyManager`. This mainly fixed the `AbstractIT` instrumented test, but should make things more robust for future use. Signed-off-by: Elv1zz <[email protected]>
Added documentation to implementation of `ActivityLifecycleCallbacks` interface. Signed-off-by: Elv1zz <[email protected]>
Use one line for each declaration, it enhances code readability. Signed-off-by: Elv1zz <[email protected]>
Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes. Signed-off-by: Elv1zz <[email protected]>
The method 'matches(AKMAlias)' has an NPath complexity of 540, current threshold is 200. This is an attempt to reduce the method's complexity. Signed-off-by: Elv1zz <[email protected]>
Added a brief documentation to empty method bodies which implement the `ActivityLifecycleCallbacks` interface. Signed-off-by: Elv1zz <[email protected]>
Fixing broken format string where `%` and `$` were mixed up. Signed-off-by: Elv1zz <[email protected]>
The `AdvancedX509ExtendedKeyManager` now extends the `X509ExtendedKeyManager`, since the documentation recommends to not directly implement the `X509KeyManager` interface, but always extend the `X509ExtendedKeyManager`. Signed-off-by: Elv1zz <[email protected]>
There is no need to keep track of the top most `Activity` anymore, since we can just use any `Context` to start a new `Activity`. So we do not have to implement the `ActivityLifecycleCallbacks` and can drop the expectation of specific `Context` implementations (`Service`, `Activity` or `Application`). Signed-off-by: Elv1zz <[email protected]>
Lint issued some warnings, which were resolved now: - replaced `switch` statement with extended `switch` - explicitly typecasted variable could be replaced with pattern variable - added `<p>` to empty lines in Javadoc comment Signed-off-by: Elv1zz <[email protected]>
By using the `class.getName()` instead of `class.getCanonicalName()` the `TAG` should not become `null`. Signed-off-by: Elv1zz <[email protected]>
Added an unit test for the `AKMAlias.matches` method before refactoring it. Signed-off-by: Elv1zz <[email protected]>
This should reduce NPath complexity of `AKMAlias.matches` method without changing its behavior. This was verified using the previously added unit test that should cover all relevant cases. Signed-off-by: Elv1zz <[email protected]>
Codacy did not like my test in several points: - The function name may not have an underscore (`_`). - Magic number (`123`) should be replaced with a named constant. - File should end with a new line. Signed-off-by: Elv1zz <[email protected]>
This part of the code was completely removed in the meantime, the So, is there anything I can do to get this PR forward? |
Awesome work @Elv1zz! I think tagging @tobiasKaminsky is appropriate as older PRs probably aren't checked for progress |
@Elv1zz to get CI running, I would like to create this branch in our repo. |
Superseeded by #1308 |
This PR adds the new
AdvancedX509KeyManager
, which is used to select, manage, and apply a TLS client certificate to establish a secure connection to a server that requires a client certificate to connect. It includes an interactive component to allow the user to select the client certificate from the device's store.The implementation is based on
InteractiveKeyManager
by Stephan Ritscher and was updated, modified, stripped-down, and now integrated into thenextcloud/android-library
, as it was requested in previous PRs #1005 and #11099 to not add dependency on a third-party library for security related code.One of the other comments in the previous PR was that there is already an implementation to support TLS client certificates in the nextcloud talk app. However, to my understanding, that approach seems to be too different to the nextcloud android app, since e.g. the talk app does not use the nextcloud android-library in the first place and has all the network related code in the app itself, so it has much stronger coupling between the components, which -- I think -- cannot be achieved in the separated architecture of the android-library and android app.
Since most logic and (minimalistic) UI is added to the library, integration into a client app requires only a few lines of code (corresponding PR to the
nextcloud/android
app will follow soon).Thanks for reviewing :)