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