4

We have a Java Web Start application signed with a certificate from CA (Thawte). The application is distributed to the hundreds of customers. They hosted it on their servers a run it over the internet or intranet on their client computers. Now it works perfect. Problem is that the application is signed without timestamp. What happens to customers when the certificate expires? Should they be able to start the app? If not, how we can help them? Does adding their server URL to the exception site list help them?

We tried to change the local time to pretend certificate expiration. Then application is blocked due to security. Adding the URL to the exception site list doesn't help:

java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Response is unreliable: its validity interval is out-of-date
at com.sun.deploy.security.RevocationChecker.checkOCSP(Unknown Source)
at com.sun.deploy.security.RevocationChecker.check(Unknown Source)
at com.sun.deploy.security.TrustDecider.checkRevocationStatus(Unknown Source)
at com.sun.deploy.security.TrustDecider.getValidationState(Unknown Source)
at com.sun.deploy.security.TrustDecider.validateChain(Unknown Source)
at com.sun.deploy.security.TrustDecider.isAllPermissionGrantedInt(Unknown Source)
at com.sun.deploy.security.TrustDecider.isAllPermissionGranted(Unknown Source)
at com.sun.javaws.security.AppPolicy.grantUnrestrictedAccess(Unknown Source)
at com.sun.javaws.security.JNLPSignedResourcesHelper.checkSignedResourcesHelper(Unknown Source)
at com.sun.javaws.security.JNLPSignedResourcesHelper.checkSignedResources(Unknown Source)
at com.sun.javaws.Launcher.prepareResources(Unknown Source)
at com.sun.javaws.Launcher.prepareAllResources(Unknown Source)
at com.sun.javaws.Launcher.prepareToLaunch(Unknown Source)
at com.sun.javaws.Launcher.prepareToLaunch(Unknown Source)
at com.sun.javaws.Launcher.launch(Unknown Source)
at com.sun.javaws.Main.launchApp(Unknown Source)
at com.sun.javaws.Main.continueInSecureThread(Unknown Source)
at com.sun.javaws.Main.access$000(Unknown Source)
at com.sun.javaws.Main$1.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Suppressed: com.sun.deploy.security.RevocationChecker$StatusUnknownException
    at com.sun.deploy.security.RevocationChecker.checkCRLs(Unknown Source)
    ... 19 more
Caused by: java.security.cert.CertPathValidatorException: Response is unreliable: its validity interval is out-of-date
at sun.security.provider.certpath.OCSPResponse.verify(Unknown Source)
at sun.security.provider.certpath.OCSP.check(Unknown Source)
at sun.security.provider.certpath.OCSP.check(Unknown Source)
at sun.security.provider.certpath.OCSP.check(Unknown Source)
at com.sun.deploy.security.RevocationChecker$2.run(Unknown Source)
at com.sun.deploy.security.RevocationChecker$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.deploy.security.RevocationChecker.doPrivilegedOCSPCheck(Unknown Source)
... 20 more

What we can do? Sure, we asked Thawte for renew our certificate and going to ask our customers for upgrade to resigned application. But we cannot cover all of them. We need to have some quick advice for them when they ask us. The expiration time is coming so any comments are welcome.

stepand76
  • 467
  • 6
  • 17
  • Sign it again, this time with the time-stamp included, and provide updated application to your customers before your original signature expires. – jariq Oct 09 '15 at 08:53
  • @jariq We are going to do it, but it is not possible to contact all of customers. We don't know who and where is our application running. It's package software. We develop it, sell it to system integrators and they install it at the end-user site... – stepand76 Oct 09 '15 at 09:58

2 Answers2

7

What happens?

WebStart's behavior highly depends on the JRE version it belongs to.

These are our test results with an application signed with a valid certificate from an official certificate autority but without timestamping after the certificate expires. Tested on Windows 7 with x64 JREs by directly executing javaws.exe in different versions and changing the system clock for simulation:

  • <= 7u21: warning message (can be hidden with check box)
  • 7u25 - 7u40: WebStart is broken in different ways, changing behavior in every update release, do not use anyway
  • 7u45 to 7u51: application is blocked at security setting "very high", warning message at setting "high" (can be hidden with check box)
  • >= 7u55: application is blocked
  • >= 8u0: application is blocked

We noticed that WebStart tries to use the most up-to-date version currently installed on the system when starting from the browser. Changing the application for JNLP files in the browser is not sufficient (Firefox). There is a lookup strategy using the JREs and JDKs installed in the Programm Files\Java folder. Calling javaws.exe from the command line or a Windows link really executes the version to test. You can see the version in the Java Console (successful start) or the Task Manager command line column (delegates to a jp2launcher.exe of another version).

Workaround

  • For us the exception site list does work (tested with j8u66). However, it seems to be tricky to enter the right URL. We think it has to be exactly the same URL as used in the JNLP file URL. When the JNLP URL is http://myhost:12345/my/app/test.jnlp the exception site http://myhost:12345/ does work. Using the IP address of myhost instead or myhost.in-my-domain.com will not match. See http://java.com/de/download/faq/exception_sitelist.xml.
  • Depending on your type of application creating a Windows desktop link to a j7u21 ...\javaws.exe <jnlp-url> may be a way out.

Signing with time stamping and a warning

Oracle states that signing with time stamping from an official time stamping authority (TSA) will prevent signatures from expiring. This allows you to prevent the problem in future releases and to deliver update releases.

Please note this warning: WebStart is happy with the time stamped signatures even after expiration of the signing certificate. However, it will block the application and state "certificate has expired or is not yet valid" at the time your TSA's certificate expires. In our tests this is at 2020-03-16 using the TSA http://tsa.starfieldtech.com/. You can see this expiration date following Timestamp: in the output of keytool -printcert -jarfile <your-signed.jar>.

Time stamping only gives you some more years on the clock of this time bomb. Depending on your type of application this may not be a problem, but for embedded applications in closed environments that have to run for the next 10 years this is a killer. (tested with j8u66)

Update from 2016-01-07: The final answer from Oracle Support concerning this issue is "There is no bug. The behaviour is expected and intentional. There will definitely be no change.". This means there is and will be no way to sign an application without expiration.

Holger
  • 380
  • 1
  • 6
0

I just want to add that the exception you see when changing the computer time, has no correlation to the expiry of the certificate. OCSP is a protocol for calling a server if a certificate is revoked or not. There is a time in the OCSP response and if your computer clock is more than 900 secs from the responded time, then this exception happens. This exception will not happen if clock is not manipulated.

This snippet is from 1.8u221 JRE sun.security.provider.certpath.OCSPResponse singleResponse has the response from OCSP server.

/*  591 */     long l = (paramDate == null) ? System.currentTimeMillis() : paramDate.getTime();
/*  592 */     Date date1 = new Date(l + MAX_CLOCK_SKEW);
/*  593 */     Date date2 = new Date(l - MAX_CLOCK_SKEW);
/*  594 */     for (SingleResponse singleResponse : this.singleResponseMap.values()) {
/*  595 */       if (debug != null) {
/*  596 */         String str = "";
/*  597 */         if (singleResponse.nextUpdate != null) {
/*  598 */           str = " until " + singleResponse.nextUpdate;
/*      */         }
/*  600 */         debug.println("OCSP response validity interval is from " + singleResponse
/*  601 */             .thisUpdate + str);
/*  602 */         debug.println("Checking validity of OCSP response on: " + new Date(l));
/*      */       } 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */       
/*  609 */       if (date1.before(singleResponse.thisUpdate) || date2
/*  610 */         .after(
/*  611 */           (singleResponse.nextUpdate != null) ? singleResponse.nextUpdate : singleResponse.thisUpdate))
/*      */       {
/*  613 */         throw new CertPathValidatorException("Response is unreliable: its validity interval is out-of-date");
/*      */       }
/*      */     } 
/*      */   }