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

[Feature Request] Ability to suppress network security popups about invalid certificates #1453

Open
itlancer opened this issue Dec 13, 2021 · 31 comments
Labels

Comments

@itlancer
Copy link

Feature Description

AIR should have ability to suppress network security popups about invalid certificates programmatically.
Right now if something goes wrong with HTTPS SSL certificate checks using URLLoader/URLStream/Loader/StageWebView/Socket/SecureSocket/NetConnection - application (OS) just show network security error/popup like these:
image
image

Such popups cause application "hanging" (sometimes crash) until user choose something. Moreover, for some retail kiosk there could be no user and application just stop working.
That why we need a way to programmatically control it:

  1. By default it should works as is. Let user decide what to do.
  2. If such network security issue happens - some event should be fired and via AS3 logic we can get all necessary information about it (including certificate information), make some additional checks to decide “block” or “allow” connection via some SecurityEvent::preventDefault() or something like that.
    In such case there shouldn't be any popups.
    And application could programmatically allow/block it and show custom visual notification without hanging/crashing.

There are a lot of different reasons of this issue:

  • Incorrect certificate
  • Network attack
  • Incorrect date/time of client device (especially for some low-cost Android TV Boxes without CMOS battery)
  • Self-signed certificates usage (often used by enterprise clients)
  • ...

You can use https://badssl.com/ to test it.

This feature need for all platforms. May be only iOS have some restrictions about that.

Related links:
https://stackoverflow.com/questions/4072377/how-can-i-bypass-or-detect-ssl-certificate-before-the-message-is-shown-in-adobe
https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/security/CertificateStatus.html

Known Workarounds

none

@2jfw
Copy link

2jfw commented Dec 13, 2021

Though this is not the answer to your request, I am pretty sure that you cannot simply suppress these notifications per default as they are coming directly from Windows itself ("Adobe uses the underlying OS certificate store", https://stackoverflow.com/questions/2187758/ssl-client-side-certificate-authentication-in-adobe-air). We are also encountering this and need to work with own trusted root certificates generated for specfic domains/hosts.

Harman would likely have to come up with a custom solution (certificate store) for this - sounds complicated but maybe I'm wrong, so please take my words with a grain of salt on this.

EDIT: In the link there is a work-around described. Maybe this helps...

@al-sabr
Copy link

al-sabr commented Dec 14, 2021

This might maybe connected to this thread : #1439

@al-sabr
Copy link

al-sabr commented Mar 22, 2022

Actually there's a hack for this problem. One might use the Windows handling capabilities of the Win32 API to always check if the specific window if showing and if yes then get the handle of the button to press and once the handle is acquired you can internally trigger the button with a virtual click and the Window will disappear.

I think each OS have their own handling API the task is to find them.

I hope this help

Windows : https://www.google.com/url?sa=t&source=web&rct=j&url=https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindow&ved=2ahUKEwi82Ongx9n2AhUP-aQKHeKJDm8QFnoECAwQAQ&usg=AOvVaw0-q9u2fhsycES_juGALyNV

@itlancer
Copy link
Author

itlancer commented Jul 5, 2023

@ajwfrost
Just check new certificateError event with Windows devices and URLLoader using latest AIR 50.2.3.1. It works as expected, thank you! Now we can suppress network security errors popups.
What I would like to see in future versions:

  1. New event as a proper class.
  2. Get information about certificate and reason of error to "make a decision" about preventing or allowing request.

Also I will try to check the same using URLStream/Loader/StageWebView/Socket/SecureSocket/NetConnection and other platforms.

@itlancer
Copy link
Author

@ajwfrost
certificateError event doesn't fired with StageWebView.
Tested with Windows devices using <UseWebView2>true</UseWebView2>.
Also tested with Android devices without <runtimeInBackgroundThread>true</runtimeInBackgroundThread>.
For testing used https://expired.badssl.com/ and https://self-signed.badssl.com/

@xiangshun110
Copy link

@itlancer hi brother,I have a question for you.
The SDK version I'm using is 50.2.3.1
the code looks like this:
loader = new URLLoader(); loader.addEventListener("certificateError", certificateError);
But I didn't get a certificateError callback event。
Is it used like this? thanks

@ajwfrost
Copy link
Collaborator

@xiangshun110 that's how it should be used yes; you'd only see that callback if we find the remote server is using a self-signed certificate though.
You can test this with https://self-signed.badssl.com/
Other certificate failures aren't (yet?) being handled in this manner ..

thanks

@itlancer
Copy link
Author

@ajwfrost
Thanks for new SecurityErrorEvent.CERTIFICATE_ERROR event.
Only issue I found for now - it just still doesn't work with StageWebView.

@itlancer
Copy link
Author

itlancer commented Aug 6, 2024

StageWebView still not support SecurityErrorEvent.CERTIFICATE_ERROR events with AIR 51.1.1.2.

@itlancer
Copy link
Author

@ajwfrost
SecurityErrorEvent.CERTIFICATE_ERROR supported by URLLoader and URLStream.

But it doesn't work with Loader. Tested with latest AIR 51.1.1.5.
Here is sample:

package {
	import flash.display.Sprite;
	import flash.net.URLRequest;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	
	public class LoaderCertificateError extends Sprite {
		private var loader:Loader = new Loader();
		
		public function LoaderCertificateError() {
			const urlRequest:URLRequest = new URLRequest("https://1000-sans.badssl.com/icons/favicon-green.ico");
			loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.CERTIFICATE_ERROR, certificateError);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, complete);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, error);
			loader.load(urlRequest);
		}
		
		private function certificateError(e:SecurityErrorEvent):void {
			trace("certificateError", e.errorID, e.text);
		}
	
		private function complete(e:Event):void {
			trace("complete", e.target.data);
		}
		
		private function error(e:IOErrorEvent):void {
			trace("error");
		}
	}
}

Also it doens't work for StageWebView.

@itlancer
Copy link
Author

@ajwfrost
Also it doesn't work with sendToURL():
sendToURL(new URLRequest("https://self-signed.badssl.com/"));
We need some way to suppress certificate errors for sendToURL() too. May be some new parameter for this method.

@itlancer
Copy link
Author

itlancer commented Oct 1, 2024

@ajwfrost
Also SecurityErrorEvent.CERTIFICATE_ERROR doesn't work with Linux. Event not dispatches at all.
Here is sample:

package {
	import flash.display.Sprite;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.events.SecurityErrorEvent;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	
	public class URLLoaderCloseError extends Sprite {
		private var urlLoader:URLLoader = new URLLoader();
		
		public function URLLoaderCloseError() {
			const urlRequest:URLRequest = new URLRequest("https://self-signed.badssl.com/");
			urlLoader.addEventListener(SecurityErrorEvent.CERTIFICATE_ERROR, certificateError);
			urlLoader.addEventListener(Event.COMPLETE, complete);
			urlLoader.addEventListener(IOErrorEvent.IO_ERROR, error);
			urlLoader.load(urlRequest);
		}
		
		private function certificateError(e:SecurityErrorEvent):void {
			trace("certificateError", e.errorID, e.text);
		}
	
		private function complete(e:Event):void {
			trace("complete");
		}
	
		private function error(e:IOErrorEvent):void {
			trace("error");
		}
	}
}

@itlancer
Copy link
Author

itlancer commented Oct 4, 2024

@ajwfrost
Also SecurityErrorEvent.CERTIFICATE_ERROR doesn't work for NetStream/NetConnection video playback (I think audio too). Just try to change date to incorrect (year 2007 for example) in OS and try to playback MP4 H.264 video via URL.

@ajwfrost
Copy link
Collaborator

To summarise the situation here: we still need to fix support for:

  • sendToURL() (and navigateToURL()?)
  • Linux-based runtimes
  • NetStream/NetConnection URLs
  • Loader
  • StageWebView

On the Loader object, we just found a place where that needed to be hooked up internally, and then the event is sent out. Will take a look at the others too..

thanks

@itlancer
Copy link
Author

@ajwfrost, exactly.
For navigateToURL() I think it's not relevant cause it just open provided URL via system default browser. So it's not related to AIR.

@itlancer
Copy link
Author

@ajwfrost, with latest AIR 51.1.2.2 it works fine with Loader and for Linux. Thanks!
Still need to be implemented for:

  • sendToURL()
  • NetStream/NetConnection URLs
  • StageWebView

Also need to be documented:
#3567
#3566
#3565

@itlancer
Copy link
Author

@ajwfrost, also should be implemented for Sound.
So the full remaining list:

  • sendToURL()
  • NetStream/NetConnection URLs
  • StageWebView
  • Sound

@Mintonist
Copy link

@itlancer
Can you confirm that it is enough to listen and catch SecurityErrorEvent.CERTIFICATE_ERROR for URLRequest to prevent security popup?

@itlancer
Copy link
Author

@Mintonist
Not for URLRequest but for URLLoader/URLStream/LoaderInfo/...
And adding SecurityErrorEvent.CERTIFICATE_ERROR listener prevent security popup.

@Mintonist
Copy link

@itlancer
and then can I recieve data in Event.COMPLETE or not?
On popup user can click 'yes' or 'no'. Can I prevent popup as it was 'yes' answer?

@ajwfrost
Copy link
Collaborator

To make the certificateError event handler act like a user hitting "yes" to proceed with a connection, you can call event.preventDefault() on the certificate error event object in that handler.

@Mintonist
Copy link

What if I don't call event.preventDefault() ?

@ajwfrost
Copy link
Collaborator

The default behaviour is to block the connection if there's an issue with the certificate.

So basically:

  1. Add an event handler for certificateError and don't call preventDefault() = block the connection
  2. Add an event handler for certificateError and call preventDefault() = allow the connection
  3. Don't add an event handler for certificateError = pop up a dialog for the user to choose

@Mintonist
Copy link

Thanks! I think this is need to be in documentation.

@Mintonist
Copy link

@ajwfrost Can it be added to flash.net.Socket ?

@ajwfrost
Copy link
Collaborator

@Mintonist it shouldn't be relevant for a normal socket .. it's only when using SSL/TLS that you'd get any certificate error, so a plain/insecure socket or HTTP (rather than HTTPS) connection would not be able to dispatch this.

@Mintonist
Copy link

Of course! Thanks!

@Mintonist
Copy link

Can anyone explain. If I use .swc library (AIR51 with SecurityErrorEvent.CERTIFICATE_ERROR) in AIR50 project (without definition of SecurityErrorEvent.CERTIFICATE_ERROR) how it will work?

@ajwfrost
Copy link
Collaborator

I would assume:

  • the SWC library would have some actionscript in it that goes along the lines of "get the property CERTIFICATE_ERROR from the class SecurityErrorEvent"
  • if this is compiled into a SWF version 50, then the above "get property" call would fail and throw a reference error or similar, presumably when verifying the function where you're adding/removing this event listener
  • if you had just used the string "certificateError" then it would compile and run fine, but no events with the type of certificateError would be dispatched in AIR v50 so it just becomes a bit of a no-op..

@Mintonist
Copy link

Mintonist commented Dec 18, 2024

Thanks!
I see problem that now we can use CERTIFICATE_ERROR but libraries like Starling (in AssetManager) don't know about it.
You need to add new listener in all part of your projects including third-party libraries or you will not get a result...
What do you think about it? Use fork library copies and modify it if we can?

I buy new certificate for my server. It use GlobalSign R6 root certificate. But not very old Android devices (from 2016-2020) don't have it in their certificate storages. So many players see the pop-ups. So I need to do something.

@ajwfrost
Copy link
Collaborator

Yes, this could be true .. sometimes it might be possible to get hold of the underlying URLStream (or similar) objects to attach your own listeners to. I guess the "proper" solution would be to fork the library, make the changes, and then create a pull request to see if they can be adopted in the next release.

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

No branches or pull requests

6 participants