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