Posts in Category "AIR"

An Update on HTTP Content Encoding in AIR Applications

In keeping with my recent HTTP theme, I want to provide an update on a change to HTTP content encoding supporting in AIR 2.0.3, which has just been released.

The HTTP protocol permits server and clients to agree on encoding a document for transfer. For text and XML documents, this can significantly reduce transfer time, as they typically compress well.

Prior to the AIR 2.0.3 update, AIR supported gzip and flate encodings only on Mac OS and Linux. On Mac OS, this was a result of using the default OS HTTP stack, which supports those encodings by default. On Linux, which has no default HTTP stack, we implemented direct support for these options.

On Windows, the capability was not available because AIR uses the OS HTTP stack, but Windows did not support these encodings prior to Vista. Therefore, AIR could not depend on this capability being present and did not enable it. Developers could work around this by managing the HTTP content encoding header themselves and performing the decompression in ActionScript, although that’s not a particularly fun option to implement.

As of the AIR 2.0.3 release, we’ve added support for gzip and flate encoding for all versions of Windows, thus bringing it to parity with Mac OS and Linux. This change applies to all applications using the 2.0 (and later) namespaces. Applications using the 2.0 namespace will automatically benefit from this change when run on the 2.0.3 and later runtime; there is no need to re-publish.

Single Sign-On and HTTP Cookies in AIR Applications

[3-Jan-11: Please see More on sharing HTTP cookies with AIR applications for an important follow-on to this post.]

Consistent with our philosophy that an AIR applications should behave like any other application on your device, AIR leverages the underlying operating system HTTP stack when making HTTP requests. A while back, I write about how this enables the use of OS facilities TLS client authentication.

Sharing the system HTTP stack also enables the use of HTTP cookie-based single sign-on mechanisms across both multiple applications and between AIR applications and the users browser. Assuming all parties use the shared HTTP stack, this will work by default. AIR applications can individually disable managing cookies in this way via URLRequestDefaults.manageCookies.

It should be noted that not all applications use the shared HTTP stack. Firefox is a notable exception, which unfortunately means that cookie-based single sign-on between Firefox and AIR applications (indeed, most desktop applications) does not work. Also, on Linux, AIR uses its own HTTP stack because there is no default OS stack available.

AIR 2, NativeProcess, and 64-bit Windows

AIR 2 includes, among other new APIs, the ability to launch and communicate with sub-processes via the NativeProcess API. The API can launch executables bundled with your application or installed separately. On Windows, it turns out that the latter can be trickier than expected when running on a 64-bit system.

64-bit versions of Windows can run both 32-bit and 64-bit processes. This makes it possible for users to transition to 64-bit over time, keeping their 32-bit applications with them until 64-bit versions are available. This is why AIR applications, which for now remain 32-bit applications, can run on 64-bit versions of Windows. Most of the time, this works seamlessly.

In order to ease porting 32-bit applications to 64-bit Windows, 64-bit applications continue to use the %windir%\system32 directory for 64-bit libraries. This is great for 64-bit applications, which continue to work, even with explicit references to this directory. However, it would break all 32-bit applications, as they can’t load the 64-bit libraries.

To work around this, Windows automatically redirects most accesses to this directory from 32-bit applications running on 64-bit Windows to a different location: %windir%\SysWOW64. (WOW64, despite its name, is the subsystem that runs 32-bit applications on 64-bit Windows.) Again, most of the time this works seamlessly.

This approach will if you’re trying to launch an executable from %windir%\system32 if there is no 32-bit version of the same executable in %windir%\SysWOW64. In this situation, you can see in Explorer that the executable exists in %windir%\system32, but when you check the same location via your 32-bit application, the file, due to redirection, will not be present. If this happens to you when using the AIR NativeProcess API, you’ll get an error (3214) that the executable you’re trying to use is invalid.

The workaround to the workaround? Starting with Windows Vista, you can force direct access to the 64-bit directory by using %windir%\sysnative. It’s not a real directory, but it is recognized by the redirection logic and pointed to the real %windir%\system32 directory. For Windows XP, you’ll have to resort to system calls to turn off redirection. For a complete description, see the MSDN File System Redirector documentation.

GlobalSign Individual Developer Certificates

I’ve posted several times in the past on the importance of using a trusted certificate, even though obtaining a trusted certificate takes both time and money. While some certification authorities continue to issue code signing certificates only to businesses, I was pleased to learn recently that GlobalSign has joined the ranks of those make certificates available to individuals as well. See the GlobalSign Code Signing page for further information.

Application Update Security and Native Application Installers

New to AIR 2 is the ability to create native application installers. By “native”, we mean that the installers are not .air files, which the desktop operating systems don’t inherently understand, but instead types they do understand: .exe, .dmg, .rpm, .deb.

Applications deployed via native installers do not have access to the Updater API, which is designed to work only with .air files. This is not as restrictive as it might seem, as an AIR 2 application deployed via a native installers has all the facilities it needs to download and launch its own updater.

Applications that take this approach must also take care to secure the download of the update itself. This is handled for you when using .air files and the Updater API. The .air file is signed, and signature validation is performed during the install. None of the contents of the .air file can be executed until after the signature is validated.

The situation is quite different for native application installers: They can generally execute code before signature validation, and may not even be signed. It is therefore critical to make sure that the update you’ve download is valid before opening it. Otherwise, you’ll have created a mechanism that can be hijacked to download and execute arbitrary code.

There are two basic approaches you can use to secure the download path: (a) use an https: download, or (b) sign the download and validate before running. The former is likely easier to set up, but the latter scales better for download support.

If you deploy your application via a native application installer, please take the time to make sure you have a functional, secure update mechanism in place.

Update Strategies for Changing Certificates

As mentioned in my previous post, switching signatures by applying a second signature is a fact of life for updating AIR applications. If you’re creating such an update to your application each time you get a new certificate, then you’ve solved half of the problem. The other half is to make sure you’ve implemented a matching update strategy in your application.

Unlike the signing half, there’s no requirement that each installed application be updated on a regular basis. This would be impossible to enforce, anyway: If a user takes their machine offline for two years, there’s little to be done. To successfully install updates over time, however, you do need to insure that the sequence of updates installed on any given machine includes one update for each certificate transition.

For example, suppose you’ve run through three certificates: C1, C2, and C3. You’ve got a user who has an older copy of your application signed with C1. To update them to the latest version signed with C3, you need to install two updates on their machine:

  1. An update making the transition from C1 to C2
  2. An update making the transition from C2 to C3

It’d be more convenient to create an update straight from C1 to C3 but, in a typical case, C1 will be long expired before you obtain C3 and therefore not useable for this purpose.

Since you can’t assume the jump from whatever version the user has to the latest version is possible, your update mechanism must provide a method of sequencing updates. That can be as simple as changing the URL used to fetch updates each time you change certificates.

This does not mean you need to have users apply all updates to your application, one by one. For example, suppose you issued three updates to your application after acquiring C2 but while C1 was still useable for applying the second signature: Then you can sign each update twice and any user with a version signed by C1 can jump straight to the latest version signed by C2. Again, what they can’t do is jump to any later version that doesn’t have the second C1 signature.

In conjunction with regular updates, an appropriate update strategy will keep application updates a seamless experience for your users.

Update Your Application Regularly

AIR includes an easy-to-use API via which applications can update themselves, and many developers issue frequent updates to their applications. This is not just a good idea: issuing an update at least once each time you renew (or change) your certificate is necessary to maintain the ability to update your application at all.

The issue arises because most code signing certificates are only valid for a limited period of time. (Certificates have to have a limited lifespan in order to keep them secure. The typical lifespan is one year.) Once a certificate has expired, AIR no longer permits it to be used to issue updates to an application. A new certificate has to be acquired, whether as a renewal or as a new purchase.

To secure the transition between those two certificates, at least one update to the application needs to be signed with both certificates, old and new. To facilitate this, AIR does allow the old certificate to be used (for this purpose only) for up to 180 days past its expiration date. In order to issue an update to your application, you must create an update to your application during this period in which both the old and new certificates are valid.

If you fail to create an update signed with both certificates you’ll find yourself unable to update the previous version of your application. You can still have users go through a manual uninstall/reinstall process–basically, uninstalling the old application and installing a new one in its place–but that’s clearly not as desirable.

To keep this all working smoothly:

  1. Replace your code signing certificate when it expires.
  2. Immediately create an update to your application, signed with both old and new certificates, after receiving your new certificate.

Note that you don’t necessarily have to publish the update you create each year, at least not right away. You might wait for a planned product release a month or two later, and apply both signatures to that update as well. Creating the update gives you a backup should you need it. More on this in my next post.

API Tip: Don’t Abuse File.applicationStorageDirectory

It was recently pointed out to me that some applications, which shall remain nameless here, are using File.applicationStorageDirectory to cache hundreds of megabytes of files. Please, don’t do this.

The File.applicationStorageDirectory property is intended to provide applications with a guaranteed writable, unique location in which they can save important information, regardless of which platform they’re running on. The information is saved to locations that are, on typical machines, backed up. On Windows, it’s saved under “<user>/Application Data”, which also roams with the user, if roaming profiles are enabled. There’s an implicit assumption here that the amount of data being stored is relatively small–megabytes at most.

Large sets of cached files should be stored elsewhere, in locations that aren’t backed up and don’t roam. AIR doesn’t include a handy property for finding such a location, but don’t let that stop you; the filesystem API lets you access any location on disk, after all. On Windows, you can use the “<user>\Local Settings\Application Data” directory (note the “Local Settings”); on Mac OS, use “<user>/Library/Caches”.

Upcoming Certificate Renewal Changes in Adobe AIR

AIR currently secures application updates published with renewed certificates by comparing the publisher ID computed from the old and new certificates. If the publisher IDs are identical the update is allowed; otherwise, it’s not.

Recently we’ve been made aware that the publisher ID computation is flawed in ways that make it quite likely that renewed certificates will not have identical publisher IDs. These range from the trivial to the unresolvable:

  • In one case, an original certificate contained a typo in the publisher’s identity. This was corrected in the renewal. However, the publisher ID computation requires that the publisher’s identity matches exactly.
  • In another case, similar, key information changed–but in one of the intermediate certificates in the certificate chain. The change was legitimate, but again fell outside the scope of changes that the publisher ID computation allows.
  • In perhaps the most serious issue, the publisher ID algorithm requires that the root certificate in the certificate chain be identical across renewals. Root certificates are typically valid for 20 years or more, so this was not anticipated as a serious limitation. However, many root certificates will be retired in the next few years in favor of certificates with longer key lengths–long before they expire.

If you’ve run into this situation, you should use the migration signature feature, which was first added in AIR 1.1. It was originally designed to allow secured updates across unrelated certificates (i.e., not renewals). As a general purpose mechanism, however, it also works just as well with renewals, whether or not they run into this issue.

There are, however, two drawbacks to the migration signature mechanism:

  1. You have to use the mechanism before your old certificate expires. Certificate renewals are often issued only after the previous certificate has expired.
  2. When you migrate between certificates your publisher ID changes. Among other things, this causes the application to lose access to any data stored in the EncryptedLocalStore.

This is an unfortunate turn of events for a feature that was designed to make things easier, and we apologize for the trouble all of this has caused. To address these issues, we will be making two significant changes in an otherwise minor release of AIR. This release is currently scheduled for December. The changes are:

  1. Applications will use a specified, not computed, publisher ID. This will allow them to change certificates without losing access to existing data.
  2. For purposes of changing certificates, certificates will be accepted as valid for six months after they expire. This allows plenty of time to renew and update the application.

Further details will be made available in conjunction with the upcoming release.

MAX 2009 Follow-up

Just a quick note to point out that my MAX 2009 talk on AIR distribution and deployment is now available on Adobe TV. Admittedly it’s more like slides-with-a-voice-over than what one would traditionally call “TV”. Oh well.

Took some great questions from the audience during the talk. If you have further questions, please post a comment or drop me an email. (My email address is in the last slide of the presentation.)