1/* 2 * Copyright (C) 2010, 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.connectivitymanagertest; 18 19import javax.xml.parsers.SAXParser; 20import javax.xml.parsers.SAXParserFactory; 21 22import org.xml.sax.Attributes; 23import org.xml.sax.SAXException; 24import org.xml.sax.helpers.DefaultHandler; 25 26import android.net.wifi.WifiConfiguration; 27import android.net.wifi.WifiConfiguration.AuthAlgorithm; 28import android.net.wifi.WifiConfiguration.IpAssignment; 29import android.net.wifi.WifiConfiguration.KeyMgmt; 30import android.net.wifi.WifiConfiguration.ProxySettings; 31import android.net.LinkAddress; 32import android.net.LinkProperties; 33import android.net.RouteInfo; 34import android.util.Log; 35 36import java.io.InputStream; 37import java.net.InetAddress; 38import java.net.UnknownHostException; 39import java.util.ArrayList; 40import java.util.HashMap; 41import java.util.List; 42 43 44/** 45 * Help class to process configurations of access points saved in an XML file. 46 * The configurations of an access point is included in tag 47 * <accesspoint></accesspoint>. The supported configuration includes: ssid, 48 * security, eap, phase2, identity, password, anonymousidentity, cacert, usercert, 49 * in which each is included in the corresponding tags. Static IP setting is also supported. 50 * Tags that can be used include: ip, gateway, networkprefixlength, dns1, dns2. All access points 51 * have to be enclosed in tags of <resources></resources>. 52 * 53 * The following is a sample configuration file for an access point using EAP-PEAP with MSCHAP2. 54 * <resources> 55 * <accesspoint> 56 * <ssid>testnet</ssid> 57 * <security>EAP</security> 58 * <eap>PEAP</eap> 59 * <phase2>MSCHAP2</phase2> 60 * <identity>donut</identity</identity> 61 * <password>abcdefgh</password> 62 * </accesspoint> 63 * </resources> 64 * 65 * Note:ssid and security have to be the first two tags 66 * for static ip setting, tag "ip" should be listed before other fields: dns, gateway, 67 * networkprefixlength. 68 */ 69public class AccessPointParserHelper { 70 private static final String KEYSTORE_SPACE = "keystore://"; 71 private static final String TAG = "AccessPointParserHelper"; 72 static final int NONE = 0; 73 static final int WEP = 1; 74 static final int PSK = 2; 75 static final int EAP = 3; 76 77 List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>(); 78 79 private int getSecurityType (String security) { 80 if (security.equalsIgnoreCase("NONE")) { 81 return NONE; 82 } else if (security.equalsIgnoreCase("WEP")) { 83 return WEP; 84 } else if (security.equalsIgnoreCase("PSK")) { 85 return PSK; 86 } else if (security.equalsIgnoreCase("EAP")) { 87 return EAP; 88 } else { 89 return -1; 90 } 91 } 92 93 private boolean validateEapValue(String value) { 94 if (value.equalsIgnoreCase("PEAP") || 95 value.equalsIgnoreCase("TLS") || 96 value.equalsIgnoreCase("TTLS")) { 97 return true; 98 } else { 99 return false; 100 } 101 } 102 103 DefaultHandler mHandler = new DefaultHandler() { 104 105 boolean ssid = false; 106 boolean security = false; 107 boolean password = false; 108 boolean ip = false; 109 boolean gateway = false; 110 boolean networkprefix = false; 111 boolean dns1 = false; 112 boolean dns2 = false; 113 boolean eap = false; 114 boolean phase2 = false; 115 boolean identity = false; 116 boolean anonymousidentity = false; 117 boolean cacert = false; 118 boolean usercert = false; 119 WifiConfiguration config = null; 120 int securityType = NONE; 121 LinkProperties mLinkProperties = null; 122 InetAddress mInetAddr = null; 123 124 @Override 125 public void startElement(String uri, String localName, String tagName, 126 Attributes attributes) throws SAXException { 127 if (tagName.equalsIgnoreCase("accesspoint")) { 128 config = new WifiConfiguration(); 129 } 130 if (tagName.equalsIgnoreCase("ssid")) { 131 ssid = true; 132 } 133 if (tagName.equalsIgnoreCase("security")) { 134 security = true; 135 } 136 if (tagName.equalsIgnoreCase("password")) { 137 password = true; 138 } 139 if (tagName.equalsIgnoreCase("eap")) { 140 eap = true; 141 } 142 if (tagName.equalsIgnoreCase("phase2")) { 143 phase2 = true; 144 } 145 if (tagName.equalsIgnoreCase("identity")) { 146 identity = true; 147 } 148 if (tagName.equalsIgnoreCase("anonymousidentity")) { 149 anonymousidentity = true; 150 } 151 if (tagName.equalsIgnoreCase("cacert")) { 152 cacert = true; 153 } 154 if (tagName.equalsIgnoreCase("usercert")) { 155 usercert = true; 156 } 157 if (tagName.equalsIgnoreCase("ip")) { 158 mLinkProperties = new LinkProperties(); 159 ip = true; 160 } 161 if (tagName.equalsIgnoreCase("gateway")) { 162 gateway = true; 163 } 164 if (tagName.equalsIgnoreCase("networkprefixlength")) { 165 networkprefix = true; 166 } 167 if (tagName.equalsIgnoreCase("dns1")) { 168 dns1 = true; 169 } 170 if (tagName.equalsIgnoreCase("dns2")) { 171 dns2 = true; 172 } 173 } 174 175 @Override 176 public void endElement(String uri, String localName, String tagName) throws SAXException { 177 if (tagName.equalsIgnoreCase("accesspoint")) { 178 if (mLinkProperties != null) { 179 config.ipAssignment = IpAssignment.STATIC; 180 config.linkProperties = mLinkProperties; 181 } else { 182 config.ipAssignment = IpAssignment.DHCP; 183 } 184 config.proxySettings = ProxySettings.NONE; 185 networks.add(config); 186 mLinkProperties = null; 187 } 188 } 189 190 @Override 191 public void characters(char ch[], int start, int length) throws SAXException { 192 if (ssid) { 193 config.SSID = new String(ch, start, length); 194 ssid = false; 195 } 196 if (security) { 197 String securityStr = (new String(ch, start, length)).toUpperCase(); 198 securityType = getSecurityType(securityStr); 199 switch (securityType) { 200 case NONE: 201 config.allowedKeyManagement.set(KeyMgmt.NONE); 202 break; 203 case WEP: 204 config.allowedKeyManagement.set(KeyMgmt.NONE); 205 config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN); 206 config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED); 207 break; 208 case PSK: 209 config.allowedKeyManagement.set(KeyMgmt.WPA_PSK); 210 break; 211 case EAP: 212 config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); 213 config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); 214 // Initialize other fields. 215 config.phase2.setValue(""); 216 config.ca_cert.setValue(""); 217 config.client_cert.setValue(""); 218 config.engine.setValue(""); 219 config.engine_id.setValue(""); 220 config.key_id.setValue(""); 221 config.identity.setValue(""); 222 config.anonymous_identity.setValue(""); 223 break; 224 default: 225 throw new SAXException(); 226 } 227 security = false; 228 } 229 if (password) { 230 String passwordStr = new String(ch, start, length); 231 int len = passwordStr.length(); 232 if (len == 0) { 233 throw new SAXException(); 234 } 235 if (securityType == WEP) { 236 if ((len == 10 || len == 26 || len == 58) && 237 passwordStr.matches("[0-9A-Fa-f]*")) { 238 config.wepKeys[0] = passwordStr; 239 } else { 240 config.wepKeys[0] = '"' + passwordStr + '"'; 241 } 242 } else if (securityType == PSK) { 243 if (passwordStr.matches("[0-9A-Fa-f]{64}")) { 244 config.preSharedKey = passwordStr; 245 } else { 246 config.preSharedKey = '"' + passwordStr + '"'; 247 } 248 } else if (securityType == EAP) { 249 config.password.setValue(passwordStr); 250 } else { 251 throw new SAXException(); 252 } 253 password = false; 254 } 255 if (eap) { 256 String eapValue = new String(ch, start, length); 257 if (!validateEapValue(eapValue)) { 258 throw new SAXException(); 259 } 260 config.eap.setValue(eapValue); 261 eap = false; 262 } 263 if (phase2) { 264 String phase2Value = new String(ch, start, length); 265 config.phase2.setValue("auth=" + phase2Value); 266 phase2 = false; 267 } 268 if (identity) { 269 String identityValue = new String(ch, start, length); 270 config.identity.setValue(identityValue); 271 identity = false; 272 } 273 if (anonymousidentity) { 274 String anonyId = new String(ch, start, length); 275 config.anonymous_identity.setValue(anonyId); 276 anonymousidentity = false; 277 } 278 if (cacert) { 279 String cacertValue = new String(ch, start, length); 280 // need to install the credentail to "keystore://" 281 config.ca_cert.setValue(KEYSTORE_SPACE); 282 cacert = false; 283 } 284 if (usercert) { 285 String usercertValue = new String(ch, start, length); 286 config.client_cert.setValue(KEYSTORE_SPACE); 287 usercert = false; 288 } 289 if (ip) { 290 try { 291 String ipAddr = new String(ch, start, length); 292 if (!InetAddress.isNumeric(ipAddr)) { 293 throw new SAXException(); 294 } 295 mInetAddr = InetAddress.getByName(ipAddr); 296 } catch (UnknownHostException e) { 297 throw new SAXException(); 298 } 299 ip = false; 300 } 301 if (gateway) { 302 try { 303 String gwAddr = new String(ch, start, length); 304 if (!InetAddress.isNumeric(gwAddr)) { 305 throw new SAXException(); 306 } 307 mLinkProperties.addRoute(new RouteInfo(InetAddress.getByName(gwAddr))); 308 } catch (UnknownHostException e) { 309 throw new SAXException(); 310 } 311 gateway = false; 312 } 313 if (networkprefix) { 314 try { 315 int nwPrefixLength = Integer.parseInt(new String(ch, start, length)); 316 if ((nwPrefixLength < 0) || (nwPrefixLength > 32)) { 317 throw new SAXException(); 318 } 319 mLinkProperties.addLinkAddress(new LinkAddress(mInetAddr, nwPrefixLength)); 320 } catch (NumberFormatException e) { 321 throw new SAXException(); 322 } 323 networkprefix = false; 324 } 325 if (dns1) { 326 try { 327 String dnsAddr = new String(ch, start, length); 328 if (!InetAddress.isNumeric(dnsAddr)) { 329 throw new SAXException(); 330 } 331 mLinkProperties.addDns(InetAddress.getByName(dnsAddr)); 332 } catch (UnknownHostException e) { 333 throw new SAXException(); 334 } 335 dns1 = false; 336 } 337 if (dns2) { 338 try { 339 String dnsAddr = new String(ch, start, length); 340 if (!InetAddress.isNumeric(dnsAddr)) { 341 throw new SAXException(); 342 } 343 mLinkProperties.addDns(InetAddress.getByName(dnsAddr)); 344 } catch (UnknownHostException e) { 345 throw new SAXException(); 346 } 347 dns2 = false; 348 } 349 } 350 }; 351 352 /** 353 * Process the InputStream in 354 * @param in is the InputStream that can be used for XML parsing 355 * @throws Exception 356 */ 357 public AccessPointParserHelper(InputStream in) throws Exception { 358 SAXParserFactory factory = SAXParserFactory.newInstance(); 359 SAXParser saxParser = factory.newSAXParser(); 360 saxParser.parse(in, mHandler); 361 } 362 363 public List<WifiConfiguration> getNetworkConfigurations() throws Exception { 364 return networks; 365 } 366} 367