Home | History | Annotate | Download | only in hotspot2
      1 /*
      2  * Copyright (C) 2017 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 
     17 package com.android.server.wifi.hotspot2;
     18 
     19 import android.net.wifi.hotspot2.PasspointConfiguration;
     20 import android.text.TextUtils;
     21 
     22 import com.android.internal.util.XmlUtils;
     23 import com.android.server.wifi.SIMAccessor;
     24 import com.android.server.wifi.WifiConfigStore;
     25 import com.android.server.wifi.WifiKeyStore;
     26 import com.android.server.wifi.util.XmlUtil;
     27 
     28 import org.xmlpull.v1.XmlPullParser;
     29 import org.xmlpull.v1.XmlPullParserException;
     30 import org.xmlpull.v1.XmlSerializer;
     31 
     32 import java.io.IOException;
     33 import java.util.ArrayList;
     34 import java.util.List;
     35 
     36 /**
     37  * Responsible for Passpoint specific configuration store data.  There are two types of
     38  * configuration data, system wide and user specific.  The system wide configurations are stored
     39  * in the share store and user specific configurations are store in the user store.
     40  *
     41  * Below are the current configuration data for each respective store file, the list will
     42  * probably grow in the future.
     43  *
     44  * Share Store (system wide configurations)
     45  * - Current provider index - use for assigning provider ID during provider creation, to make
     46  *                            sure each provider will have an unique ID across all users.
     47  *
     48  * User Store (user specific configurations)
     49  * - Provider list - list of Passpoint provider configurations
     50  *
     51  */
     52 public class PasspointConfigStoreData implements WifiConfigStore.StoreData {
     53     private static final String XML_TAG_SECTION_HEADER_PASSPOINT_CONFIG_DATA =
     54             "PasspointConfigData";
     55     private static final String XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER_LIST =
     56             "ProviderList";
     57     private static final String XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER =
     58             "Provider";
     59     private static final String XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION =
     60             "Configuration";
     61 
     62     private static final String XML_TAG_PROVIDER_ID = "ProviderID";
     63     private static final String XML_TAG_CREATOR_UID = "CreatorUID";
     64     private static final String XML_TAG_CA_CERTIFICATE_ALIAS = "CaCertificateAlias";
     65     private static final String XML_TAG_CLIENT_CERTIFICATE_ALIAS = "ClientCertificateAlias";
     66     private static final String XML_TAG_CLIENT_PRIVATE_KEY_ALIAS = "ClientPrivateKeyAlias";
     67 
     68     private static final String XML_TAG_PROVIDER_INDEX = "ProviderIndex";
     69 
     70     private final WifiKeyStore mKeyStore;
     71     private final SIMAccessor mSimAccessor;
     72     private final DataSource mDataSource;
     73 
     74     /**
     75      * Interface define the data source for the Passpoint configuration store data.
     76      */
     77     public interface DataSource {
     78         /**
     79          * Retrieve the provider list from the data source.
     80          *
     81          * @return List of {@link PasspointProvider}
     82          */
     83         List<PasspointProvider> getProviders();
     84 
     85         /**
     86          * Set the provider list in the data source.
     87          *
     88          * @param providers The list of providers
     89          */
     90         void setProviders(List<PasspointProvider> providers);
     91 
     92         /**
     93          * Retrieve the current provider index.
     94          *
     95          * @return long
     96          */
     97         long getProviderIndex();
     98 
     99         /**
    100          * Set the current provider index.
    101          *
    102          * @param providerIndex The provider index used for provider creation
    103          */
    104         void setProviderIndex(long providerIndex);
    105     }
    106 
    107     PasspointConfigStoreData(WifiKeyStore keyStore, SIMAccessor simAccessor,
    108             DataSource dataSource) {
    109         mKeyStore = keyStore;
    110         mSimAccessor = simAccessor;
    111         mDataSource = dataSource;
    112     }
    113 
    114     @Override
    115     public void serializeData(XmlSerializer out, boolean shared)
    116             throws XmlPullParserException, IOException {
    117         if (shared) {
    118             serializeShareData(out);
    119         } else {
    120             serializeUserData(out);
    121         }
    122     }
    123 
    124     @Override
    125     public void deserializeData(XmlPullParser in, int outerTagDepth, boolean shared)
    126             throws XmlPullParserException, IOException {
    127         if (shared) {
    128             deserializeShareData(in, outerTagDepth);
    129         } else {
    130             deserializeUserData(in, outerTagDepth);
    131         }
    132     }
    133 
    134     @Override
    135     public void resetData(boolean shared) {
    136         if (shared) {
    137             resetShareData();
    138         } else {
    139             resetUserData();
    140         }
    141     }
    142 
    143     @Override
    144     public String getName() {
    145         return XML_TAG_SECTION_HEADER_PASSPOINT_CONFIG_DATA;
    146     }
    147 
    148     @Override
    149     public boolean supportShareData() {
    150         return true;
    151     }
    152 
    153     /**
    154      * Serialize share data (system wide Passpoint configurations) to a XML block.
    155      *
    156      * @param out The output stream to serialize data to
    157      * @throws XmlPullParserException
    158      * @throws IOException
    159      */
    160     private void serializeShareData(XmlSerializer out) throws XmlPullParserException, IOException {
    161         XmlUtil.writeNextValue(out, XML_TAG_PROVIDER_INDEX, mDataSource.getProviderIndex());
    162     }
    163 
    164     /**
    165      * Serialize user data (user specific Passpoint configurations) to a XML block.
    166      *
    167      * @param out The output stream to serialize data to
    168      * @throws XmlPullParserException
    169      * @throws IOException
    170      */
    171     private void serializeUserData(XmlSerializer out) throws XmlPullParserException, IOException {
    172         serializeProviderList(out, mDataSource.getProviders());
    173     }
    174 
    175     /**
    176      * Serialize the list of Passpoint providers from the data source to a XML block.
    177      *
    178      * @param out The output stream to serialize data to
    179      * @param providerList The list of providers to serialize
    180      * @throws XmlPullParserException
    181      * @throws IOException
    182      */
    183     private void serializeProviderList(XmlSerializer out, List<PasspointProvider> providerList)
    184             throws XmlPullParserException, IOException {
    185         if (providerList == null) {
    186             return;
    187         }
    188         XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER_LIST);
    189         for (PasspointProvider provider : providerList) {
    190             serializeProvider(out, provider);
    191         }
    192         XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER_LIST);
    193     }
    194 
    195     /**
    196      * Serialize a Passpoint provider to a XML block.
    197      *
    198      * @param out The output stream to serialize data to
    199      * @param provider The provider to serialize
    200      * @throws XmlPullParserException
    201      * @throws IOException
    202      */
    203     private void serializeProvider(XmlSerializer out, PasspointProvider provider)
    204             throws XmlPullParserException, IOException {
    205         XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER);
    206         XmlUtil.writeNextValue(out, XML_TAG_PROVIDER_ID, provider.getProviderId());
    207         XmlUtil.writeNextValue(out, XML_TAG_CREATOR_UID, provider.getCreatorUid());
    208         XmlUtil.writeNextValue(out, XML_TAG_CA_CERTIFICATE_ALIAS,
    209                 provider.getCaCertificateAlias());
    210         XmlUtil.writeNextValue(out, XML_TAG_CLIENT_CERTIFICATE_ALIAS,
    211                 provider.getClientCertificateAlias());
    212         XmlUtil.writeNextValue(out, XML_TAG_CLIENT_PRIVATE_KEY_ALIAS,
    213                 provider.getClientPrivateKeyAlias());
    214         if (provider.getConfig() != null) {
    215             XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION);
    216             PasspointXmlUtils.serializePasspointConfiguration(out, provider.getConfig());
    217             XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION);
    218         }
    219         XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER);
    220     }
    221 
    222     /**
    223      * Deserialize share data (system wide Passpoint configurations) from the input stream.
    224      *
    225      * @param in The input stream to read data from
    226      * @param outerTagDepth The tag depth of the current XML section
    227      * @throws XmlPullParserException
    228      * @throws IOException
    229      */
    230     private void deserializeShareData(XmlPullParser in, int outerTagDepth)
    231             throws XmlPullParserException, IOException {
    232         while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
    233             String[] valueName = new String[1];
    234             Object value = XmlUtil.readCurrentValue(in, valueName);
    235             if (valueName[0] == null) {
    236                 throw new XmlPullParserException("Missing value name");
    237             }
    238             switch (valueName[0]) {
    239                 case XML_TAG_PROVIDER_INDEX:
    240                     mDataSource.setProviderIndex((long) value);
    241                     break;
    242                 default:
    243                     throw new XmlPullParserException("Unknown value under share store data "
    244                             + valueName[0]);
    245             }
    246         }
    247     }
    248 
    249     /**
    250      * Deserialize user data (user specific Passpoint configurations) from the input stream.
    251      *
    252      * @param in The input stream to read data from
    253      * @param outerTagDepth The tag depth of the current XML section
    254      * @throws XmlPullParserException
    255      * @throws IOException
    256      */
    257     private void deserializeUserData(XmlPullParser in, int outerTagDepth)
    258             throws XmlPullParserException, IOException {
    259         String[] headerName = new String[1];
    260         while (XmlUtil.gotoNextSectionOrEnd(in, headerName, outerTagDepth)) {
    261             switch (headerName[0]) {
    262                 case XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER_LIST:
    263                     mDataSource.setProviders(deserializeProviderList(in, outerTagDepth + 1));
    264                     break;
    265                 default:
    266                     throw new XmlPullParserException("Unknown Passpoint user store data "
    267                             + headerName[0]);
    268             }
    269         }
    270     }
    271 
    272     /**
    273      * Deserialize a list of Passpoint providers from the input stream.
    274      *
    275      * @param in The input stream to read data form
    276      * @param outerTagDepth The tag depth of the current XML section
    277      * @return List of {@link PasspointProvider}
    278      * @throws XmlPullParserException
    279      * @throws IOException
    280      */
    281     private List<PasspointProvider> deserializeProviderList(XmlPullParser in, int outerTagDepth)
    282             throws XmlPullParserException, IOException {
    283         List<PasspointProvider> providerList = new ArrayList<>();
    284         while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_PASSPOINT_PROVIDER,
    285                 outerTagDepth)) {
    286             providerList.add(deserializeProvider(in, outerTagDepth + 1));
    287         }
    288         return providerList;
    289     }
    290 
    291     /**
    292      * Deserialize a Passpoint provider from the input stream.
    293      *
    294      * @param in The input stream to read data from
    295      * @param outerTagDepth The tag depth of the current XML section
    296      * @return {@link PasspointProvider}
    297      * @throws XmlPullParserException
    298      * @throws IOException
    299      */
    300     private PasspointProvider deserializeProvider(XmlPullParser in, int outerTagDepth)
    301             throws XmlPullParserException, IOException {
    302         long providerId = Long.MIN_VALUE;
    303         int creatorUid = Integer.MIN_VALUE;
    304         String caCertificateAlias = null;
    305         String clientCertificateAlias = null;
    306         String clientPrivateKeyAlias = null;
    307         PasspointConfiguration config = null;
    308         while (XmlUtils.nextElementWithin(in, outerTagDepth)) {
    309             if (in.getAttributeValue(null, "name") != null) {
    310                 // Value elements.
    311                 String[] name = new String[1];
    312                 Object value = XmlUtil.readCurrentValue(in, name);
    313                 switch (name[0]) {
    314                     case XML_TAG_PROVIDER_ID:
    315                         providerId = (long) value;
    316                         break;
    317                     case XML_TAG_CREATOR_UID:
    318                         creatorUid = (int) value;
    319                         break;
    320                     case XML_TAG_CA_CERTIFICATE_ALIAS:
    321                         caCertificateAlias = (String) value;
    322                         break;
    323                     case XML_TAG_CLIENT_CERTIFICATE_ALIAS:
    324                         clientCertificateAlias = (String) value;
    325                         break;
    326                     case XML_TAG_CLIENT_PRIVATE_KEY_ALIAS:
    327                         clientPrivateKeyAlias = (String) value;
    328                         break;
    329                 }
    330             } else {
    331                 if (!TextUtils.equals(in.getName(),
    332                         XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION)) {
    333                     throw new XmlPullParserException("Unexpected section under Provider: "
    334                             + in.getName());
    335                 }
    336                 config = PasspointXmlUtils.deserializePasspointConfiguration(in,
    337                         outerTagDepth + 1);
    338             }
    339         }
    340         if (providerId == Long.MIN_VALUE) {
    341             throw new XmlPullParserException("Missing provider ID");
    342         }
    343         if (config == null) {
    344             throw new XmlPullParserException("Missing Passpoint configuration");
    345         }
    346         return new PasspointProvider(config, mKeyStore, mSimAccessor, providerId, creatorUid,
    347                 caCertificateAlias, clientCertificateAlias, clientPrivateKeyAlias);
    348     }
    349 
    350     /**
    351      * Reset share data (system wide Passpoint configurations).
    352      */
    353     private void resetShareData() {
    354         mDataSource.setProviderIndex(0);
    355     }
    356 
    357     /**
    358      * Reset user data (user specific Passpoint configurations).
    359      */
    360     private void resetUserData() {
    361         mDataSource.setProviders(new ArrayList<PasspointProvider>());
    362     }
    363 }
    364 
    365