1/*
2 * Copyright (C) 2013 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.settings.vpn2;
18
19import android.util.Log;
20
21import com.android.internal.net.VpnProfile;
22
23import org.xml.sax.Attributes;
24import org.xml.sax.SAXException;
25import org.xml.sax.helpers.DefaultHandler;
26
27import java.io.IOException;
28import java.io.InputStream;
29import java.util.HashMap;
30import java.util.Map;
31
32import javax.xml.parsers.ParserConfigurationException;
33import javax.xml.parsers.SAXParser;
34import javax.xml.parsers.SAXParserFactory;
35
36/**
37 * Parse VPN profiles from an XML file
38 */
39public class VpnProfileParser {
40    private final static String TAG = "VpnProfileParser";
41    private static Map<Integer, VpnInfo> mVpnPool = new HashMap<Integer, VpnInfo>();
42
43    static DefaultHandler mHandler = new DefaultHandler() {
44        boolean name;
45        boolean type;
46        boolean server;
47        boolean username;
48        boolean password;
49        boolean dnsServers;
50        boolean searchDomains;
51        boolean routes;
52        boolean mppe;
53        boolean l2tpSecret;
54        boolean ipsecIdentifier;
55        boolean ipsecSecret;
56        boolean ipsecUserCert;
57        boolean ipsecCaCert;
58        boolean ipsecServerCert;
59        boolean certFile;
60        boolean certFilePassword;
61        VpnProfile profile = null;
62        VpnInfo vpnInfo = null;
63
64
65        @Override
66        public void startElement(String uri, String localName, String tagName,
67                Attributes attributes) throws SAXException {
68            if (tagName.equalsIgnoreCase("vpn")) {
69                //create a new VPN profile
70                profile = new VpnProfile(Long.toHexString(System.currentTimeMillis()));
71                vpnInfo = new VpnInfo(profile);
72            }
73            if (tagName.equalsIgnoreCase("name")) {
74                name = true;
75            }
76            if (tagName.equalsIgnoreCase("type")) {
77                type = true;
78            }
79            if (tagName.equalsIgnoreCase("server")) {
80                server = true;
81            }
82            if (tagName.equalsIgnoreCase("username")) {
83                username = true;
84            }
85            if (tagName.equalsIgnoreCase("password")) {
86                password = true;
87            }
88            if (tagName.equalsIgnoreCase("dnsServers")) {
89                dnsServers = true;
90            }
91            if (tagName.equalsIgnoreCase("searchDomains")) {
92                searchDomains = true;
93            }
94            if (tagName.equalsIgnoreCase("mppe")) {
95                mppe = true;
96            }
97            if (tagName.equalsIgnoreCase("l2tpSecret")) {
98                l2tpSecret = true;
99            }
100            if (tagName.equalsIgnoreCase("ipsecIdentifier")) {
101                ipsecIdentifier = true;
102            }
103            if (tagName.equalsIgnoreCase("ipsecSecret")) {
104                ipsecSecret = true;
105            }
106            if (tagName.equalsIgnoreCase("ipsecUserCert")) {
107                ipsecUserCert = true;
108            }
109            if (tagName.equalsIgnoreCase("ipsecCaCert")) {
110                ipsecCaCert = true;
111            }
112            if (tagName.equalsIgnoreCase("ipsecServerCert")) {
113                ipsecServerCert = true;
114            }
115            if (tagName.equalsIgnoreCase("routes")) {
116                routes = true;
117            }
118            if (tagName.equalsIgnoreCase("cert-file")) {
119                certFile = true;
120            }
121            if (tagName.equalsIgnoreCase("cert-file-password")) {
122                certFilePassword = true;
123            }
124        }
125
126        @Override
127        public void endElement(String uri, String localName, String tagName) throws SAXException {
128            if (tagName.equalsIgnoreCase("vpn")) {
129                mVpnPool.put(profile.type, vpnInfo);
130            }
131        }
132
133        @Override
134        public void characters(char ch[], int start, int length) throws SAXException {
135            String strValue = new String(ch, start, length);
136            if (name) {
137                profile.name = strValue;
138                name = false;
139            }
140            if (type) {
141                int t = getVpnProfileType(strValue);
142                if (t < 0) {
143                    throw new SAXException("not a valid VPN type");
144                } else {
145                    profile.type = t;
146                }
147                type = false;
148            }
149            if (server) {
150                profile.server = strValue;
151                server = false;
152            }
153            if (username) {
154                profile.username = strValue;
155                username = false;
156            }
157            if (password) {
158                profile.password = strValue;
159                password = false;
160            }
161            if (dnsServers) {
162                profile.dnsServers = strValue;
163                dnsServers = false;
164            }
165            if (searchDomains) {
166                profile.searchDomains = strValue;
167                searchDomains = false;
168            }
169            if (mppe) {
170                profile.mppe = Boolean.valueOf(strValue);
171                mppe = false;
172            }
173            if (l2tpSecret) {
174                profile.l2tpSecret = strValue;
175                l2tpSecret = false;
176            }
177            if (ipsecIdentifier) {
178                profile.ipsecIdentifier = strValue;
179                ipsecIdentifier = false;
180            }
181            if (ipsecSecret) {
182                profile.ipsecSecret = strValue;
183                ipsecSecret = false;
184            }
185            if (ipsecUserCert) {
186                profile.ipsecUserCert = strValue;
187                ipsecUserCert = false;
188            }
189            if (ipsecCaCert) {
190                profile.ipsecCaCert = strValue;
191                ipsecCaCert = false;
192            }
193            if (ipsecServerCert) {
194                profile.ipsecServerCert = strValue;
195                ipsecServerCert = false;
196            }
197            if (routes) {
198                profile.routes = strValue;
199                routes = false;
200            }
201            if (certFile) {
202                vpnInfo.setCertificateFile(strValue);
203                certFile = false;
204            }
205            if (certFilePassword) {
206                vpnInfo.setPassword(strValue);
207                certFilePassword = false;
208            }
209        }
210
211        private int getVpnProfileType(String type) {
212            if (type.equalsIgnoreCase("TYPE_PPTP")) {
213                return VpnProfile.TYPE_PPTP;
214            } else if (type.equalsIgnoreCase("TYPE_L2TP_IPSEC_PSK")) {
215                return VpnProfile.TYPE_L2TP_IPSEC_PSK;
216            } else if (type.equalsIgnoreCase("TYPE_L2TP_IPSEC_RSA")) {
217                return VpnProfile.TYPE_L2TP_IPSEC_RSA;
218            } else if (type.equalsIgnoreCase("TYPE_IPSEC_XAUTH_PSK")) {
219                return VpnProfile.TYPE_IPSEC_XAUTH_PSK;
220            } else if (type.equalsIgnoreCase("TYPE_IPSEC_XAUTH_RSA")) {
221                return VpnProfile.TYPE_IPSEC_XAUTH_RSA;
222            } else if (type.equalsIgnoreCase("TYPE_IPSEC_HYBRID_RSA")) {
223                return VpnProfile.TYPE_IPSEC_HYBRID_RSA;
224            } else {
225                Log.v(TAG, "Invalid VPN type: " + type);
226                return -1;
227            }
228        }
229    };
230
231    public static Map<Integer, VpnInfo> parse(InputStream in) {
232        try {
233            SAXParserFactory factory = SAXParserFactory.newInstance();
234            SAXParser saxParser = factory.newSAXParser();
235            saxParser.parse(in, mHandler);
236        } catch (SAXException e) {
237            Log.e(TAG, "Parse vpn profile exception: " + e.toString());
238        } catch (IOException e) {
239            Log.e(TAG, "Parse vpn profile exception: " + e.toString());
240        } catch (ParserConfigurationException e) {
241            Log.e(TAG, "Parse vpn profile exception: " + e.toString());
242        } finally {
243            return mVpnPool;
244        }
245    }
246}
247