OSDN Git Service

Update the Statement Service. DO NOT MERGE
authorJoseph Wen <josephwen@google.com>
Thu, 23 Apr 2015 19:45:07 +0000 (15:45 -0400)
committerJoseph Wen <josephwen@google.com>
Wed, 20 May 2015 20:37:51 +0000 (16:37 -0400)
For security reason, disallow HTTP include files if the source asset is
a HTTPS site or an Android app.
Change the include statement field name from "delegate" to "include".

Bug: 20323096
Change-Id: Ifc12b61657c9c89a670b9d7c3220853321c15dea

packages/StatementService/src/com/android/statementservice/retriever/AbstractAsset.java
packages/StatementService/src/com/android/statementservice/retriever/AndroidAppAsset.java
packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
packages/StatementService/src/com/android/statementservice/retriever/Utils.java
packages/StatementService/src/com/android/statementservice/retriever/WebAsset.java

index e71cf54..bb6bdbb 100644 (file)
@@ -63,4 +63,10 @@ public abstract class AbstractAsset {
             throws AssociationServiceException {
         return AssetFactory.create(assetJson);
     }
+
+    /**
+     * If this is the source asset of a statement file, should the retriever follow
+     * any insecure (non-HTTPS) include statements made by the asset.
+     */
+    public abstract boolean followInsecureInclude();
 }
index 0c96038..8ead90b 100644 (file)
@@ -99,6 +99,12 @@ import java.util.Locale;
         return getPackageName().hashCode();
     }
 
+    @Override
+    public boolean followInsecureInclude() {
+        // Non-HTTPS includes are not allowed in Android App assets.
+        return false;
+    }
+
     /**
      * Checks that the input is a valid Android app asset.
      *
index 6516516..548149e 100644 (file)
@@ -136,7 +136,8 @@ import java.util.List;
         }
     }
 
-    private Result retrieveStatementFromUrl(String url, int maxIncludeLevel, AbstractAsset source)
+    private Result retrieveStatementFromUrl(String urlString, int maxIncludeLevel,
+                                            AbstractAsset source)
             throws AssociationServiceException {
         List<Statement> statements = new ArrayList<Statement>();
         if (maxIncludeLevel < 0) {
@@ -145,7 +146,12 @@ import java.util.List;
 
         WebContent webContent;
         try {
-            webContent = mUrlFetcher.getWebContentFromUrl(new URL(url),
+            URL url = new URL(urlString);
+            if (!source.followInsecureInclude()
+                    && !url.getProtocol().toLowerCase().equals("https")) {
+                return Result.create(statements, DO_NOT_CACHE_RESULT);
+            }
+            webContent = mUrlFetcher.getWebContentFromUrl(url,
                     HTTP_CONTENT_SIZE_LIMIT_IN_BYTES, HTTP_CONNECTION_TIMEOUT_MILLIS);
         } catch (IOException e) {
             return Result.create(statements, DO_NOT_CACHE_RESULT);
index 4828ff9..969aa88 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.statementservice.retriever;
 
+import android.util.Log;
+
 import com.android.volley.Cache;
 import com.android.volley.NetworkResponse;
 import com.android.volley.toolbox.HttpHeaderParser;
@@ -39,6 +41,7 @@ import java.util.Map;
  * @hide
  */
 public class URLFetcher {
+    private static final String TAG = URLFetcher.class.getSimpleName();
 
     private static final long DO_NOT_CACHE_RESULT = 0L;
     private static final int INPUT_BUFFER_SIZE_IN_BYTES = 1024;
@@ -63,11 +66,17 @@ public class URLFetcher {
         connection.setConnectTimeout(connectionTimeoutMillis);
         connection.setReadTimeout(connectionTimeoutMillis);
         connection.setUseCaches(true);
+        connection.setInstanceFollowRedirects(false);
         connection.addRequestProperty("Cache-Control", "max-stale=60");
 
+        if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
+            Log.e(TAG, "The responses code is not 200 but "  + connection.getResponseCode());
+            return new WebContent("", DO_NOT_CACHE_RESULT);
+        }
+
         if (connection.getContentLength() > fileSizeLimit) {
-            throw new AssociationServiceException("The content size of the url is larger than "
-                    + fileSizeLimit);
+            Log.e(TAG, "The content size of the url is larger than "  + fileSizeLimit);
+            return new WebContent("", DO_NOT_CACHE_RESULT);
         }
 
         Long expireTimeMillis = getExpirationTimeMillisFromHTTPHeader(connection.getHeaderFields());
index 44af864..afb4c75 100644 (file)
@@ -61,7 +61,7 @@ public final class Utils {
      */
     public static final String ASSET_DESCRIPTOR_FIELD_RELATION = "relation";
     public static final String ASSET_DESCRIPTOR_FIELD_TARGET = "target";
-    public static final String DELEGATE_FIELD_DELEGATE = "delegate";
+    public static final String DELEGATE_FIELD_DELEGATE = "include";
 
     private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
             'A', 'B', 'C', 'D', 'E', 'F' };
index ca9e62d..947087a 100644 (file)
@@ -39,6 +39,7 @@ import java.util.Locale;
 /* package private */ final class WebAsset extends AbstractAsset {
 
     private static final String MISSING_FIELD_FORMAT_STRING = "Expected %s to be set.";
+    private static final String SCHEME_HTTP = "http";
 
     private final URL mUrl;
 
@@ -105,6 +106,12 @@ import java.util.Locale;
         return toJson().hashCode();
     }
 
+    @Override
+    public boolean followInsecureInclude() {
+        // Only allow insecure include file if the asset scheme is http.
+        return SCHEME_HTTP.equals(getScheme());
+    }
+
     /**
      * Checks that the input is a valid web asset.
      *