-
Notifications
You must be signed in to change notification settings - Fork 130
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
Self-signed certificate support #106
Comments
Try this APK, based off the allow-bad-certs branch: This just allows all bad certificates, so I won't put this in the main branch. Just wondering, why don't you just use Let's Encrypt to get a proper certificate? |
This one works, thanks :) |
Upon further usage of allow-bad-certs version it seems like I was careless to assume, that if I can see the library, everything works. Neither downloads, nor playing songs work. |
Oh yeah, I forgot about native connections (the player and downloader are both native code). I'll look and see if there's any way of allowing bad certs. About your setup though, are you connecting through an IP or a domain name? If it's a domain name, you should be able to get a certificate pretty easily. |
It's a domain name, but not mine, it's ISP's. This same domain name is also used by ISP on their website, e.g. their website is example.com and DNS name to my assigned public IP is hostXXXX.example.com. Hence there's no way they would give me the private key to their certificate. |
You may be able to get a certificate for just your subdomain: https://stackoverflow.com/questions/39322112/multiple-subdomains-with-lets-encrypt |
That would require action from ISP side, since they're the owner of the whole domain with all subdomains. |
Let's Encrypt's "most common" challenge type just requests a web path on your server with the certificate, no DNS required. I doubt it would work if your ISP has some kind of wildcard certificate for all domains though. |
Okay, somehow I was sure that DNS-01 is a "must" initially, and only then either DNS-01, or HTTP-01 is used for automatic renewing. My bad :D |
I have run into this problem with my setup at home and here's my scenario. None of my services are publicly available, instead, I have an SDN setup using ZeroTier with an nginx proxy server that serves certificates locally. I have my root certificates installed on my user's devices so that they are able to have remote access including https with no open ports. This allows me the ability for my users to access everything as though it were on the public internet without having it actually available to the internet for security purposes. Would there be a way to have this app use the user certificate stores provided by the OS? |
Im assuming ZeroTier works by you connecting to an IP? If you control a domain, you could use the DNS-01 challenge. If not, it looks like ZeroTier's network is encrypted, however data may not be encrypted when travelling over the LAN. I'll have a look at allowing custom certificates since I'm sure there are people out there who can't use a regular certificate, but last time I looked the only stuff I could find was just saying to disable certificate error handling, which isn't exactly secure. |
ZeroTier uses peer to peer with root servers to negotiate the connection so unfortunately, everything on the network operates with virtual lan addresses' and node IDs, not publicly routeable. I have no idea how you get access to the certificates trusted by the operating system but both Android and IOS allow you to trust foreign certificates. That's how I get my browsers to still tell me the webpage is secure. As long as my root certificate is installed at the OS level, it shows as a trusted cert. I would assume that there's a way to access the trusted certificates from the OS. Love the app otherwise! |
I'll have a look into it then, or I'll at least add an option to disable certificate checking. |
Same thing here.
=> can't use HTTP/DNS challenge and have to use self-signed certificated :( Would be great if application will promt about self-signed certs, and make user accept it, like browser do. |
Hello, i'm bumping this issue cause i use a local CA to sign my certificates but it seems that finamp dosen't use Android local user CA base to check if it's trusted or not. I do want to still use my own CA so without disabling certificate checking, could that be possible ? Thx ! |
I believe this is an issue with Dart (or maybe BoringSSL?). I'll have a look into it because it's an annoying issue but no promises since poking around a programming language's source code isn't the easiest thing in the world. |
Why not just add a checkbox on login screen? Just let user choose trust the server or not? |
Along the lines of the previous suggestion, I'd propose as an alternative to using the system's CAs, apps like this should allow permanent exceptions the way a browser does when you click through all the warnings. It's basically a TOFU model because it only adds an exception for that specific certificate. If you change the certificate you're back to the warning page, or in the case of this app you'd be back to the login page. |
From what I can see even system certificates are not trusted. (And I'm aware that this barely makes sense as a statement.) I'm trying to connect to a Jellyfin instance that has a known good self-signed certificate for which I have the root CA for the signing authority in my system bundle and I'm getting the handshake error. Is this the expected behaviour? From the Flutter documentation it seems like CAs that are part of the system bundle should be respected. 😕 Edit: After a bit of searching it seems this thread describes the situation quite well ... which is that even if I speak fluent x.509 I barely understand the Dart developers' explanation. 😝 |
Alright, uh, so mostly bad news. I've been digging down this 🐰 🕳️ and Flutter simply does not support using the system bundles at all since Chopper does not respect I tried building the app while injecting my root CA as an additional anchor ... and even that's not being respected. You can find sample code (that cannot work) under this commit avanier@229f038 . You'll see on the same branch as a drive-by I also tried updating Chopper to I think the only realistic solution may be to add a checkbox to ignore the error like @zuoez02 suggests. Otherwise, to properly allow the use of system bundles would require getting rid of Chopper for something that makes native calls with the system API. Not a small task, and I'm not even sure it's possible at all under Flutter. (Lowly sysadmin here, I know absolutely nothing of Android development.) |
Yeah... It's a really weird omission from Dart, such a shame that we can't support it |
I wonder if Chopper can simply be updated to respect system certs or if 'per cert hash' CAs can be allow-listed. Most solutions floating on Flutter's Issues list all revolve around modifying the Trust Anchor and such, which is fine by me (on a per-cert case similar to Mozilla Firefox's old methods before they went fully moronic against non-$$$ certs). ...I notice Flutter has over 5K Issues...wow. |
I'll have to have a look to see how disabling certs worked, iirc you got a callback when something went wrong, so you might be able to override it for a specific cert. Also, this isn't Chopper's fault, it's an issue in Dart. Otherwise, this would be a simple "move to a library that does support custom certificates" |
If I recall, any custom callback circumvention has issues with Google Playstore certification/qualification? I believe I read that somewhere within Flutter's 5K Issues. I think for now it'd be best to just add a checkbox to ignore issues, but perhaps alert the user when the thumbprint of the cert has changed, if so. A decent-ish middle-ground until devs learn to stop using bad SSL/TLS backends that don't respect system-store certs. This problem is prevalent across far too many softwares for me to maintain. Epidemic. |
Some relevant issues: dart-lang/sdk#48056 This function also looks interesting, we could have a manual option for now: https://api.dart.dev/stable/2.19.4/dart-io/SecurityContext/setTrustedCertificates.html |
This doesn't seem to be getting any fixes, despite the situation being rather small to handle. I'd think this kind of issue would be a much higher priority than theming and coloring, eh. How about releasing two builds, then, one with the worst option of allowing all certs and one without? (Or just provide a bool-toggled checkbox...) |
I'll get it sorted for the next release, which should hopefully be out this month. I've been busy with uni work since the last release, so I haven't been able to contribute much (a similar thing happened last year) |
University should definitely come first then, totally understand. Awesome. :) I think the “safest” option for this would be to present a dialog to ask the user if they'd like to store the thumbprint of certs in a string array (of thumbprints) when attempting any connection and do thumbprint validation in the |
If |
As stated in this Issue: Google won't allow developers to include options like that if they're going to use the Play Store. For versions through F-Droid, entirely possible. To allow Finamp to use the system store (certificate store) the backend library (not controlled by Finamp developer(s)) needs to implement and respect proper design. Edit: It would definitely be nice to at least get the option for F-Droid builds. |
Yes. I understand it's a restriction with Google play. I'm personally using FDroid and I just can't use finamp when my servers certificate is not accepted. I don't know how much of a maintenance effort it would be to do two versions, but it would be very handy. Especially regarding the fact that the used library/environment does not seem to address the issue. Edit: I believe that the impossibility to use self signed certificates should be mentioned in the Known Issues section to avoid confusion. |
It'd be rather simple and easy, just a pain to make sure it is F-Droid's compilation. If you're familiar with C/C++, think
Agreed, regardless of whether F-Droid has enabled builds or not. It should also note that Jellyfin's app can do music, too, just not as designed for music player-like interaction. I've been using it instead, despite limitations. |
Just to recap:
I agree that adding a checkbox that explicitly disables all checks. This may or may not be supported by Google Play, but a custom build for download from GitHub should be entirely possible, once he issues above are solved. |
The native code may use the system stores as intended, I haven't got around to this as I'm selfishly not affected by it myself |
Can you clarify what you mean by may? |
I haven't actually checked but I'd assume ExoPlayer/AVPlayer would respect system certs as other native apps do |
You can add certs to be trusted, it would work, you'd just need to implement, but you'd run into the same Google PlayStore issue. They don't allow that.
Same issue, Google PlayStore. Edit: If the native backend brings support then it'd work and you wouldn't need to do anything at all.
GitHub, especially F-Droid, that'd be awesome. |
I can't find anything from Google saying that ignoring certificate errors isn't allowed. Browsers let you do it, after all |
I can't recall where I saw it (from Google) but it stated that apps that attempt to modify (specifically to reduce) security by providing a work-around like this would be violating the Play Store's policy because it puts the end user "at risk." It has to do with the API used to verifying certificates, that's what they check (edit: as I was informed at the time I ran into this issue a long while back with other apks, unrelated to signing). If it uses a custom function to bypass validation (what this does) then it's not allowed. This wasn't where I saw the issue at all, it was from Google's own development docs. I can't find that info from memory, I do little Android development. A quick search popped that up demonstrating. Relevant Snippet: You must present the error every time, though. If you want to get around that you need to add the CA as a cert (store it, append it, give the user a way to manage that, required) and load it on startup every time, or wait until the backend trusts the system store instead of loading its own certs or whatever screwy thing they're doing. |
I'd argue a checkbox that's not checked by default and maybe hidden in an "advanced settings" menu is not a "vulnerability that exposes users to risk", it's a compatibility option. |
That's literally all you have to do, make it a non-default option. Just overriding to accept all without informing the user and allowing them to reject/prevent is what Google won't allow. Having it as an option that is off by default is what they want. I felt the easiest way to implement the fix regardless of the backend's support was to quite literally attempt connection and if ERR present the cert chain[0] (will be root of cert-chain if using custom CA or will be self-signed, etc) info to allow user to connect or to connect and add the thumbprint to an allowlist (to allow 'do not show again for this server' functionality, can compare the thumbprint and allow). Allow managing that list, rather simple. I'd write the code myself if Android Studio didn't suck so much as an IDE. Better would be to store the cert itself and add as trusted CA. For cert chains, present each cert. |
@OdinVex feel free to write the code, no need to use Android Studio. VS Code is all you need. But I don't think the allowlist and thumbprint detection is as easy as it seems. This is a cross-platform framework, almost nothing is consistent or easy to access when it comes to low-level functionality... |
The code took 15 minutes to write. It's the <screaming rampage> UI <new curse words> stuff that's in my way. I've already implemented it in Finamp's Settings, the callback to detect if it's been approved before,, etc. Presents simple dialogs to confirm connection, warn if the cert changed, stores per host and per port and per cert thumbprint. Edit: As for VS Code, I don't touch MicroJunk's stuff. |
@OdinVex if you already have mostly working code, why not open a draft PR so we can take a look and get it ready to merge? :) |
The UI to remove/reset the list also needs implementing. I might indeed let someone else handle that, I've metaphorically lost my mind hate-thinking at Android, Java, Dart, Flutter... I prefer Assembly/C/C++. At the moment I'm running some test code to make sure it behaves map-wise the way it should. I suspect |
I'd be happy to help out with UI issues. Looking forward to the PR! |
Here is the initial Pull Request. See the notes. Edit: For everyone unfamiliar with coding for Android following the thread: This is just back-end work, I don't use Dart/Flutter front-ends, nor did I provide a way to access a list of certificates overridden. That should come easily to a front-end developer and you could theoretically have a final working solution today, depending on how much effort can be put into it. A simple menu in configuration/settings after login to edit overrides, a simple dialog with proper contextual messages/warnings on connect, and automatic "connection reattempt after decision" is all this needs to be a final working solution. |
I use step-ca to provide an internal cert authority for services on my private (nebula based) mesh network. I install the root certificate to all the devices in the network, including my phone, to allow for apps like jellyfin to use TLS connections without issue. This works on all apps except finamp. It works on the official jellyfin app, for example. If I understand this thread correctly, this is because the Dart language does not have an interface to check against user installed certificates on android? Is there an open issue for this upstream? I'd be happy to ping that thread as well. |
Check out (and build) the |
Is any progress being made on this, especially for the FDroid version? |
Unfortunately not by me, I auto-patch bundled software and root my devices, I'm also porting phones to Linux (think Postmarket OS) to dump Android, so I'm out. :/ |
The Flutter app for Immich has recently added support for this, so we should be able to follow their approach. I've left a comment about it in #546. I don't use self-signed certs myself, so I'd appreciate someone with more experience in that regard to give it a go. @OdinVex Finamp also runs on Linux now and I've heared of people using it on PostmarketOS/ARM. Just thought I'd let you know, in case you want to keep using it ^^ |
I looked into how they did it. It's the "will get your app banned from the Play Store if Google finds out" way. Google is strict about that API and specifically warns (threatens, actually) developers from doing that. |
I guess we'll just wait a bit and see what happens to Immich then ^^ |
Originally Google would scan binaries to see if they attempted to override/hook/utilize that API but it's been a few years. The F-Droid version could get away with it no problem. I always tried to use F-Droid versions anyway when I was on Android. |
I've set up a self-signed certificate on my Jellyfin server and installed it also as a trusted root CA on my devices. It works fine without security warnings on Chrome (both Windows and Android) and on Android apps, like official Jellyfin and Gelli, except Finamp. When I try to connect to my server in Finamp 0.5.1, I get
HandshakeException: Handshake error in client (OS Error: CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate(handshake.cc:359))
Certificate extensions:
The text was updated successfully, but these errors were encountered: