Home | History | Annotate | Download | only in parser
      1 /*
      2  * Copyright 2016, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.managedprovisioning.parser;
     17 
     18 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
     19 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
     20 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
     21 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
     22 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE;
     23 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM;
     24 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER;
     25 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION;
     26 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
     27 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM;
     28 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCALE;
     29 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCAL_TIME;
     30 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR;
     31 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION;
     32 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE;
     33 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_HIDDEN;
     34 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PAC_URL;
     35 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PASSWORD;
     36 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_BYPASS;
     37 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_HOST;
     38 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PROXY_PORT;
     39 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SECURITY_TYPE;
     40 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SSID;
     41 import static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC;
     42 import static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED;
     43 import static com.android.managedprovisioning.TestUtils.createTestAdminExtras;
     44 import static com.android.managedprovisioning.parser.MessageParser.EXTRA_PROVISIONING_DEVICE_ADMIN_SUPPORT_SHA1_PACKAGE_CHECKSUM;
     45 import static com.android.managedprovisioning.parser.MessageParser.EXTRA_PROVISIONING_STARTED_BY_TRUSTED_SOURCE;
     46 
     47 import android.accounts.Account;
     48 import android.app.admin.DevicePolicyManager;
     49 import android.content.ComponentName;
     50 import android.content.Context;
     51 import android.content.Intent;
     52 import android.nfc.NdefMessage;
     53 import android.nfc.NdefRecord;
     54 import android.nfc.NfcAdapter;
     55 import android.os.PersistableBundle;
     56 import android.test.AndroidTestCase;
     57 import android.test.suitebuilder.annotation.SmallTest;
     58 import android.util.Base64;
     59 
     60 import com.android.managedprovisioning.common.IllegalProvisioningArgumentException;
     61 import com.android.managedprovisioning.common.Utils;
     62 import com.android.managedprovisioning.model.PackageDownloadInfo;
     63 import com.android.managedprovisioning.model.ProvisioningParams;
     64 import com.android.managedprovisioning.model.WifiInfo;
     65 
     66 import java.io.ByteArrayOutputStream;
     67 import java.util.Locale;
     68 import java.util.Properties;
     69 
     70 import org.mockito.Mock;
     71 import org.mockito.MockitoAnnotations;
     72 
     73 /** Tests for {@link PropertiesProvisioningDataParser} */
     74 @SmallTest
     75 public class PropertiesProvisioningDataParserTest extends AndroidTestCase {
     76     private static final String TEST_PACKAGE_NAME = "com.afwsamples.testdpc";
     77     private static final ComponentName TEST_COMPONENT_NAME =
     78             ComponentName.unflattenFromString(
     79                     "com.afwsamples.testdpc/com.afwsamples.testdpc.DeviceAdminReceiver");
     80     private static final long TEST_LOCAL_TIME = 1456939524713L;
     81     private static final Locale TEST_LOCALE = Locale.UK;
     82     private static final String TEST_TIME_ZONE = "GMT";
     83     private static final Integer TEST_MAIN_COLOR = 65280;
     84     private static final boolean TEST_STARTED_BY_TRUSTED_SOURCE = true;
     85     private static final boolean TEST_LEAVE_ALL_SYSTEM_APP_ENABLED = true;
     86     private static final boolean TEST_SKIP_ENCRYPTION = true;
     87     private static final boolean TEST_SKIP_USER_SETUP = true;
     88     private static final Account TEST_ACCOUNT_TO_MIGRATE =
     89             new Account("user (at) gmail.com", "com.google");
     90 
     91     // Wifi info
     92     private static final String TEST_SSID = "TestWifi";
     93     private static final boolean TEST_HIDDEN = true;
     94     private static final String TEST_SECURITY_TYPE = "WPA2";
     95     private static final String TEST_PASSWORD = "GoogleRock";
     96     private static final String TEST_PROXY_HOST = "testhost.com";
     97     private static final int TEST_PROXY_PORT = 7689;
     98     private static final String TEST_PROXY_BYPASS_HOSTS = "http://host1.com;https://host2.com";
     99     private static final String TEST_PAC_URL = "pac.test.com";
    100     private static final WifiInfo TEST_WIFI_INFO = WifiInfo.Builder.builder()
    101             .setSsid(TEST_SSID)
    102             .setHidden(TEST_HIDDEN)
    103             .setSecurityType(TEST_SECURITY_TYPE)
    104             .setPassword(TEST_PASSWORD)
    105             .setProxyHost(TEST_PROXY_HOST)
    106             .setProxyPort(TEST_PROXY_PORT)
    107             .setProxyBypassHosts(TEST_PROXY_BYPASS_HOSTS)
    108             .setPacUrl(TEST_PAC_URL)
    109             .build();
    110 
    111     // Device admin package download info
    112     private static final String TEST_DOWNLOAD_LOCATION =
    113             "http://example/dpc.apk";
    114     private static final String TEST_COOKIE_HEADER =
    115             "Set-Cookie: sessionToken=foobar; Expires=Thu, 18 Feb 2016 23:59:59 GMT";
    116     private static final byte[] TEST_PACKAGE_CHECKSUM = new byte[] { '1', '2', '3', '4', '5' };
    117     private static final byte[] TEST_SIGNATURE_CHECKSUM = new byte[] { '5', '4', '3', '2', '1' };
    118     private static final int TEST_MIN_SUPPORT_VERSION = 17689;
    119     private static final PackageDownloadInfo TEST_DOWNLOAD_INFO =
    120             PackageDownloadInfo.Builder.builder()
    121                     .setLocation(TEST_DOWNLOAD_LOCATION)
    122                     .setCookieHeader(TEST_COOKIE_HEADER)
    123                     .setPackageChecksum(TEST_PACKAGE_CHECKSUM)
    124                     .setSignatureChecksum(TEST_SIGNATURE_CHECKSUM)
    125                     .setMinVersion(TEST_MIN_SUPPORT_VERSION)
    126                     .build();
    127 
    128     @Mock
    129     private Context mContext;
    130 
    131     private PropertiesProvisioningDataParser mPropertiesProvisioningDataParser;
    132 
    133     @Override
    134     public void setUp() {
    135         // this is necessary for mockito to work
    136         System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
    137 
    138         MockitoAnnotations.initMocks(this);
    139 
    140         mPropertiesProvisioningDataParser = new PropertiesProvisioningDataParser(new Utils());
    141     }
    142 
    143     public void testParse_nfcProvisioningIntent() throws Exception {
    144         // GIVEN a NFC provisioning intent with all supported data.
    145         Properties props = new Properties();
    146         ByteArrayOutputStream stream = new ByteArrayOutputStream();
    147         props.setProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, TEST_PACKAGE_NAME);
    148         props.setProperty(
    149                 EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
    150                 TEST_COMPONENT_NAME.flattenToString());
    151         setTestWifiInfo(props);
    152         setTestTimeTimeZoneAndLocale(props);
    153         setTestDeviceAdminDownload(props);
    154         // GIVEN this intent requested to support SHA1 package checksum.
    155         props.setProperty(
    156                 EXTRA_PROVISIONING_DEVICE_ADMIN_SUPPORT_SHA1_PACKAGE_CHECKSUM,
    157                 Boolean.toString(true));
    158         props.setProperty(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, getTestAdminExtrasString());
    159         props.setProperty(
    160                 EXTRA_PROVISIONING_SKIP_ENCRYPTION,
    161                 Boolean.toString(TEST_SKIP_ENCRYPTION));
    162         // GIVEN main color is supplied even though it is not supported in NFC provisioning.
    163         props.setProperty(EXTRA_PROVISIONING_MAIN_COLOR, Integer.toString(TEST_MAIN_COLOR));
    164 
    165         props.store(stream, "NFC provisioning intent" /* data description */);
    166 
    167         NdefRecord record = NdefRecord.createMime(
    168                 DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC,
    169                 stream.toByteArray());
    170         NdefMessage ndfMsg = new NdefMessage(new NdefRecord[]{record});
    171 
    172         Intent intent = new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED)
    173                 .setType(MIME_TYPE_PROVISIONING_NFC)
    174                 .putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, new NdefMessage[]{ndfMsg});
    175 
    176         // WHEN the intent is parsed by the parser.
    177         ProvisioningParams params = mPropertiesProvisioningDataParser.parse(intent, mContext);
    178 
    179 
    180         // THEN ProvisionParams is constructed as expected.
    181         assertEquals(
    182                 ProvisioningParams.Builder.builder()
    183                         // THEN NFC provisioning is translated to ACTION_PROVISION_MANAGED_DEVICE
    184                         // action.
    185                         .setProvisioningAction(ACTION_PROVISION_MANAGED_DEVICE)
    186                         .setDeviceAdminComponentName(TEST_COMPONENT_NAME)
    187                         .setDeviceAdminPackageName(TEST_PACKAGE_NAME)
    188                         .setDeviceAdminDownloadInfo(
    189                                 PackageDownloadInfo.Builder.builder()
    190                                         .setLocation(TEST_DOWNLOAD_LOCATION)
    191                                         .setCookieHeader(TEST_COOKIE_HEADER)
    192                                         .setPackageChecksum(TEST_PACKAGE_CHECKSUM)
    193                                         .setSignatureChecksum(TEST_SIGNATURE_CHECKSUM)
    194                                         .setMinVersion(TEST_MIN_SUPPORT_VERSION)
    195                                         // THEN it supports SHA1 package checksum.
    196                                         .setPackageChecksumSupportsSha1(true)
    197                                         .build())
    198                         .setLocalTime(TEST_LOCAL_TIME)
    199                         .setLocale(TEST_LOCALE)
    200                         .setTimeZone(TEST_TIME_ZONE)
    201                         // THEN main color is not supported in NFC intent.
    202                         .setMainColor(null)
    203                         .setSkipEncryption(TEST_SKIP_ENCRYPTION)
    204                         .setWifiInfo(TEST_WIFI_INFO)
    205                         .setAdminExtrasBundle(getTestAdminExtrasPersistableBundle())
    206                         .setStartedByTrustedSource(true)
    207                         .build(),
    208                 params);
    209     }
    210 
    211     public void testParse_OtherIntentsThrowsException() {
    212         // GIVEN a managed device provisioning intent and some extras.
    213         Intent intent = new Intent(ACTION_PROVISION_MANAGED_DEVICE)
    214                 .putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, TEST_PACKAGE_NAME)
    215                 .putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, TEST_COMPONENT_NAME)
    216                 .putExtra(EXTRA_PROVISIONING_SKIP_ENCRYPTION, TEST_SKIP_ENCRYPTION)
    217                 .putExtra(EXTRA_PROVISIONING_MAIN_COLOR, TEST_MAIN_COLOR)
    218                 .putExtra(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, TEST_ACCOUNT_TO_MIGRATE);
    219 
    220         try {
    221             // WHEN the intent is parsed by the parser.
    222             ProvisioningParams params = mPropertiesProvisioningDataParser.parse(intent, mContext);
    223             fail("PropertiesProvisioningDataParser doesn't support intent other than NFC. "
    224                     + "IllegalProvisioningArgumentException should be thrown");
    225         } catch (IllegalProvisioningArgumentException e) {
    226             // THEN IllegalProvisioningArgumentException is thrown.
    227         }
    228     }
    229 
    230     private static Properties setTestWifiInfo(Properties props) {
    231         props.setProperty(EXTRA_PROVISIONING_WIFI_SSID, TEST_SSID);
    232         props.setProperty(EXTRA_PROVISIONING_WIFI_SECURITY_TYPE, TEST_SECURITY_TYPE);
    233         props.setProperty(EXTRA_PROVISIONING_WIFI_PASSWORD, TEST_PASSWORD);
    234         props.setProperty(EXTRA_PROVISIONING_WIFI_PROXY_HOST, TEST_PROXY_HOST);
    235         props.setProperty(EXTRA_PROVISIONING_WIFI_PROXY_BYPASS, TEST_PROXY_BYPASS_HOSTS);
    236         props.setProperty(EXTRA_PROVISIONING_WIFI_PAC_URL, TEST_PAC_URL);
    237         props.setProperty(EXTRA_PROVISIONING_WIFI_PROXY_PORT, Integer.toString(TEST_PROXY_PORT));
    238         props.setProperty(EXTRA_PROVISIONING_WIFI_HIDDEN, Boolean.toString(TEST_HIDDEN));
    239         return props;
    240     }
    241 
    242     private static Properties setTestTimeTimeZoneAndLocale(Properties props) {
    243         props.setProperty(EXTRA_PROVISIONING_LOCAL_TIME, Long.toString(TEST_LOCAL_TIME));
    244         props.setProperty(EXTRA_PROVISIONING_TIME_ZONE, TEST_TIME_ZONE);
    245         props.setProperty(EXTRA_PROVISIONING_LOCALE, MessageParser.localeToString(TEST_LOCALE));
    246         return props;
    247     }
    248 
    249     private static Properties setTestDeviceAdminDownload(Properties props) {
    250         props.setProperty(
    251                 EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE,
    252                 Integer.toString(TEST_MIN_SUPPORT_VERSION));
    253         props.setProperty(
    254                 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION,
    255                 TEST_DOWNLOAD_LOCATION);
    256         props.setProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER,
    257                 TEST_COOKIE_HEADER);
    258         props.setProperty(
    259                 EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM,
    260                 Base64.encodeToString(TEST_PACKAGE_CHECKSUM,
    261                         Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP));
    262         props.setProperty(
    263                 EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM,
    264                 Base64.encodeToString(TEST_SIGNATURE_CHECKSUM,
    265                         Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP));
    266         return props;
    267     }
    268 
    269     private static String getTestAdminExtrasString() throws Exception {
    270         Properties props = new Properties();
    271         ByteArrayOutputStream stream = new ByteArrayOutputStream();
    272 
    273         PersistableBundle bundle = getTestAdminExtrasPersistableBundle();
    274         for (String key : bundle.keySet()) {
    275             props.setProperty(key, bundle.getString(key));
    276         }
    277         props.store(stream, "ADMIN_EXTRAS_BUNDLE" /* data description */);
    278 
    279         return stream.toString();
    280     }
    281 
    282     private static PersistableBundle getTestAdminExtrasPersistableBundle() {
    283         PersistableBundle bundle = new PersistableBundle();
    284         bundle.putString("key1", "val1");
    285         bundle.putString("key2", "val2");
    286         bundle.putString("key3", "val3");
    287         return bundle;
    288     }
    289 }
    290