diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/html/training/articles/security-gms-provider.jd | 298 | ||||
-rw-r--r-- | docs/html/training/training_toc.cs | 8 |
2 files changed, 306 insertions, 0 deletions
diff --git a/docs/html/training/articles/security-gms-provider.jd b/docs/html/training/articles/security-gms-provider.jd new file mode 100644 index 0000000..0d3cf1e --- /dev/null +++ b/docs/html/training/articles/security-gms-provider.jd @@ -0,0 +1,298 @@ +page.title=Updating Your Security Provider to Protect Against SSL Exploits +page.tags="network","certificates" + +page.article=true +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> +<h2>In this document</h2> +<ol class="nolist"> + <li><a href="#patching">Patching the Security Provider with + ProviderInstaller</a></li> + <li><a href="#example_sync">Patching Synchronously</a></li> + <li><a href="#example_async">Patching Asynchronously</a></li> + +</ol> + + +<h2>See also</h2> +<ul> + <li><a href="{@docRoot}google/play-services/">Google Play Services</a></li> + <li><a href="https://www.openssl.org/news/secadv_20140605.txt">OpenSSL + Security Advisory [05 Jun 2014]: SSL/TLS MITM vulnerability + (CVE-2014-0224)</a></li> + <li><a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-0224"> + Vulnerability Summary for CVE-2014-0224</a></li> +</ul> +</div> +</div> + + +<p> Android relies on a security {@link java.security.Provider Provider} to +provide secure network communications. However, from time to time, +vulnerabilities are found in the default security provider. To protect against +these vulnerabilities, <a href="{@docRoot}google/play-services/">Google Play +services</a> provides a way to automatically update a device's security provider +to protect against known exploits. By calling Google Play services methods, your +app can ensure that it's running on a device that has the latest updates to +protect against known exploits.</p> + +<p>For example, a vulnerability was discovered in OpenSSL +(<a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-0224">CVE-2014-0224</a>) +that can leave apps open to a "man-in-the-middle" attack that decrypts +secure traffic without either side knowing. With Google Play services version +5.0, a fix is available, but apps must ensure that this fix is installed. By +using the Google Play services methods, your app can ensure that it's running +on a device that's secured against that attack.</p> + +<p class="caution"><strong>Caution: </strong>Updating a device's security {@link +java.security.Provider Provider} does <em>not</em> update {@link +android.net.SSLCertificateSocketFactory +android.net.SSLCertificateSocketFactory}. Rather than using this class, we +encourage app developers to use high-level methods for interacting with +cryptography. Most apps can use APIs like {@link +javax.net.ssl.HttpsURLConnection}, {@link org.apache.http.client.HttpClient}, +and {@link android.net.http.AndroidHttpClient} without needing to set a custom +{@link javax.net.ssl.TrustManager} or create an {@link +android.net.SSLCertificateSocketFactory}.</p> + +<h2 id="patching">Patching the Security Provider with ProviderInstaller</h2> + +<p>To update a device's security provider, use the +<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html">{@code ProviderInstaller}</a> +class. You can verify that the security provider is up-to-date (and update it, +if necessary) by calling +that class's <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a> +(or <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html#installIfNeededAsync(android.content.Context, com.google.android.gms.security.ProviderInstaller.ProviderInstallListener)">{@code installIfNeededAsync()}</a>) +method.</p> + +<p>When you call <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a>, the +<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html">{@code ProviderInstaller}</a> +does the following:</p> + +<ul> + <li>If the device's {@link java.security.Provider Provider} is successfully + updated (or is already up-to-date), the method returns normally.</li> + <li>If the device's Google Play services library is out of date, the method + throws + <a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesRepairableException.html">{@code GooglePlayServicesRepairableException}</a>. + The app can then catch this exception and show + the user an appropriate dialog box to update Google Play services.</li> + <li>If a non-recoverable error occurs, the method throws + <a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesNotAvailableException.html">{@code GooglePlayServicesNotAvailableException}</a> + to indicate that it is unable to update the {@link java.security.Provider + Provider}. The app can then catch the exception and choose an appropriate + course of action, such as displaying the standard + <a href="{@docRoot}reference/com/google/android/gms/common/SupportErrorDialogFragment.html">fix-it flow diagram</a>.</li> +</ul> + +<p>The +<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html#installIfNeededAsync(android.content.Context, com.google.android.gms.security.ProviderInstaller.ProviderInstallListener)">{@code installIfNeededAsync()}</a> +method behaves similarly, except that instead of +throwing exceptions, it calls the appropriate callback method to indicate +success or failure.</p> + +<p>If <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a> +needs to install a new {@link java.security.Provider Provider}, this can take +anywhere from 30-50 milliseconds (on more recent devices) to 350 ms (on older +devices). If the security provider is already up-to-date, the method takes a +negligible amount of time. To avoid affecting user experience:</p> + +<ul> + <li>Call + <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a> + from background networking threads immediately when the threads are loaded, + instead of waiting for the thread to try to use the network. (There's no harm + in calling the method multiple times, since it returns immediately if the + security provider doesn't need updating.)</li> + + <li>If user experience will be affected by the thread blocking--for example, + if the call is from an activity in the UI thread--call the asynchronous + version of the method, + <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html#installIfNeededAsync(android.content.Context, com.google.android.gms.security.ProviderInstaller.ProviderInstallListener)">{@code installIfNeededAsync()}</a>. + (Of course, if you do this, you need to wait for the operation to finish + before you attempt any secure communications. The + <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html">{@code ProviderInstaller}</a> + calls your listener's <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.ProviderInstallListener.html#onProviderInstalled()">{@code onProviderInstalled()}</a> + method to signal success.)</li> +</ul> + +<p class="warning"><strong>Warning:</strong> If the +<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html">{@code ProviderInstaller}</a> +is unable to install an updated {@link java.security.Provider Provider}, +your device's security provider might be vulnerable to known exploits. Your app +should behave as if all HTTP communication is unencrypted.</p> + +<p>Once the {@link java.security.Provider Provider} is updated, all calls to +security APIs (including SSL APIs) are routed through it. +(However, this does not apply to {@link android.net.SSLCertificateSocketFactory +android.net.SSLCertificateSocketFactory}, which remains vulnerable to such +exploits as +<a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-0224">CVE-2014-0224</a>.)</p> + +<h2 id="example_sync">Patching Synchronously</h2> + +<p>The simplest way to patch the security provider is to call the synchronous +method <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a>. +This is appropriate if user experience won't be affected by the thread blocking +while it waits for the operation to finish.</p> + +<p>For example, here's an implementation of a <a href="{@docRoot}training/sync-adapters">sync adapter</a> that updates the security provider. Since a sync +adapter runs in the background, it's okay if the thread blocks while waiting +for the security provider to be updated. The sync adapter calls +<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a> to +update the security provider. If the method returns normally, the sync adapter +knows the security provider is up-to-date. If the method throws an exception, +the sync adapter can take appropriate action (such as prompting the user to +update Google Play services).</p> + +<pre>/** + * Sample sync adapter using {@link ProviderInstaller}. + */ +public class SyncAdapter extends AbstractThreadedSyncAdapter { + + ... + + // This is called each time a sync is attempted; this is okay, since the + // overhead is negligible if the security provider is up-to-date. + @Override + public void onPerformSync(Account account, Bundle extras, String authority, + ContentProviderClient provider, SyncResult syncResult) { + try { + ProviderInstaller.installIfNeeded(getContext()); + } catch (GooglePlayServicesRepairableException e) { + + // Indicates that Google Play services is out of date, disabled, etc. + + // Prompt the user to install/update/enable Google Play services. + GooglePlayServicesUtil.showErrorNotification( + e.getConnectionStatusCode(), getContext()); + + // Notify the SyncManager that a soft error occurred. + syncResult.stats.numIOExceptions++; + return; + + } catch (GooglePlayServicesNotAvailableException e) { + // Indicates a non-recoverable error; the ProviderInstaller is not able + // to install an up-to-date Provider. + + // Notify the SyncManager that a hard error occurred. + syncResult.stats.numAuthExceptions++; + return; + } + + // If this is reached, you know that the provider was already up-to-date, + // or was successfully updated. + } +}</pre> + +<h2 id="example_async">Patching Asynchronously</h2> + +<p>Updating the security provider can take as much as 350 milliseconds (on +older devices). If you're doing the update on a thread that directly affects +user experience, such as the UI thread, you don't want to make a synchronous +call to update the provider, since that can result in the app or device +freezing until the operation finishes. Instead, you should use the asynchronous +method +<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html#installIfNeededAsync(android.content.Context, com.google.android.gms.security.ProviderInstaller.ProviderInstallListener)">{@code installIfNeededAsync()}</a>. +That method indicates its success or failure by calling callbacks.</p> + +<p>For example, here's some code that updates the security provider in an +activity in the UI thread. The activity calls <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html#installIfNeededAsync(android.content.Context, com.google.android.gms.security.ProviderInstaller.ProviderInstallListener)">{@code installIfNeededAsync()}</a> +to update the provider, and designates itself as the listener to receive success +or failure notifications. If the security provider is up-to-date or is +successfully updated, the activity's +<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.ProviderInstallListener.html#onProviderInstalled()">{@code onProviderInstalled()}</a> +method is called, and the activity knows communication is secure. If the +provider cannot be updated, the activity's +<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.ProviderInstallListener.html#onProviderInstallFailed(int, android.content.Intent)">{@code onProviderInstallFailed()}</a> +method is called, and the activity can take appropriate action (such as +prompting the user to update Google Play services).</p> + +<pre>/** + * Sample activity using {@link ProviderInstaller}. + */ +public class MainActivity extends Activity + implements ProviderInstaller.ProviderInstallListener { + + private static final int ERROR_DIALOG_REQUEST_CODE = 1; + + private boolean mRetryProviderInstall; + + //Update the security provider when the activity is created. + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ProviderInstaller.installIfNeededAsync(this, this); + } + + /** + * This method is only called if the provider is successfully updated + * (or is already up-to-date). + */ + @Override + protected void onProviderInstalled() { + // Provider is up-to-date, app can make secure network calls. + } + + /** + * This method is called if updating fails; the error code indicates + * whether the error is recoverable. + */ + @Override + protected void onProviderInstallFailed(int errorCode, Intent recoveryIntent) { + if (GooglePlayServicesUtil.isUserRecoverableError(errorCode)) { + // Recoverable error. Show a dialog prompting the user to + // install/update/enable Google Play services. + GooglePlayServicesUtil.showErrorDialogFragment( + errorCode, + this, + ERROR_DIALOG_REQUEST_CODE, + new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + // The user chose not to take the recovery action + onProviderInstallerNotAvailable(); + } + }); + } else { + // Google Play services is not available. + onProviderInstallerNotAvailable(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == ERROR_DIALOG_REQUEST_CODE) { + // Adding a fragment via GooglePlayServicesUtil.showErrorDialogFragment + // before the instance state is restored throws an error. So instead, + // set a flag here, which will cause the fragment to delay until + // onPostResume. + mRetryProviderInstall = true; + } + } + + /** + * On resume, check to see if we flagged that we need to reinstall the + * provider. + */ + @Override + protected void onPostResume() { + super.onPostResult(); + if (mRetryProviderInstall) { + // We can now safely retry installation. + ProviderInstall.installIfNeededAsync(this, this); + } + mRetryProviderInstall = false; + } + + private void onProviderInstallerNotAvailable() { + // This is reached if the provider cannot be updated for some reason. + // App should consider all HTTP communication to be vulnerable, and take + // appropriate action. + } +} +</pre> diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index 4407d30..4dd57ab 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -1487,6 +1487,14 @@ results." >Security with HTTPS and SSL</a> </li> + <li> + <a href="<?cs var:toroot ?>training/articles/security-gms-provider.html" + description= + "How to use and update Google Play services security provider, to + protect against SSL exploits." + >Updating Your Security Provider to Protect Against SSL Exploits</a> + </li> + <li class="nav-section"> <div class="nav-section-header"> <a href="<?cs var:toroot ?>training/enterprise/index.html" |