WifiEnterpriseConfig.java revision 7fee7232ee2ae45fb3cd4fcce314e8f1101ae8db
19b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff/* 29b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Copyright (C) 2013 The Android Open Source Project 39b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 49b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Licensed under the Apache License, Version 2.0 (the "License"); 59b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * you may not use this file except in compliance with the License. 69b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * You may obtain a copy of the License at 79b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 89b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * http://www.apache.org/licenses/LICENSE-2.0 99b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 109b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Unless required by applicable law or agreed to in writing, software 119b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * distributed under the License is distributed on an "AS IS" BASIS, 129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * See the License for the specific language governing permissions and 149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * limitations under the License. 159b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 169b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffpackage android.net.wifi; 179b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 189b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport android.os.Parcel; 199b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport android.os.Parcelable; 209b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport android.security.Credentials; 219b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport android.text.TextUtils; 2226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 2326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.io.ByteArrayInputStream; 2426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.KeyFactory; 2526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.NoSuchAlgorithmException; 2626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.PrivateKey; 2726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.cert.CertificateEncodingException; 2826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.cert.CertificateException; 2926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.cert.CertificateFactory; 3026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.cert.X509Certificate; 3126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.spec.InvalidKeySpecException; 3226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriffimport java.security.spec.PKCS8EncodedKeySpec; 339b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport java.util.HashMap; 349b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffimport java.util.Map; 359b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 36ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde/** 37fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * Enterprise configuration details for Wi-Fi. Stores details about the EAP method 38fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * and any associated credentials. 39fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff */ 409b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriffpublic class WifiEnterpriseConfig implements Parcelable { 419b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 42ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 43ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String EMPTY_VALUE = "NULL"; 44ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 45ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String EAP_KEY = "eap"; 46ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 47ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String PHASE2_KEY = "phase2"; 48ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 49ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String IDENTITY_KEY = "identity"; 50ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 51ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String ANON_IDENTITY_KEY = "anonymous_identity"; 52ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 53ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String PASSWORD_KEY = "password"; 54ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 55ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String SUBJECT_MATCH_KEY = "subject_match"; 56ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 57ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String OPP_KEY_CACHING = "proactive_key_caching"; 58ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** 59ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde * String representing the keystore OpenSSL ENGINE's ID. 60ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde * @hide 61ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde */ 62ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String ENGINE_ID_KEYSTORE = "keystore"; 63ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde 64ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** 65ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde * String representing the keystore URI used for wpa_supplicant. 66ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde * @hide 67ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde */ 68ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String KEYSTORE_URI = "keystore://"; 69ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde 70ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** 71ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde * String to set the engine value to when it should be enabled. 72ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde * @hide 73ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde */ 74ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String ENGINE_ENABLE = "1"; 75ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde 76ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** 77ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde * String to set the engine value to when it should be disabled. 78ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde * @hide 79ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde */ 80ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String ENGINE_DISABLE = "0"; 81ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde 82ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 83ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String CA_CERT_PREFIX = KEYSTORE_URI + Credentials.CA_CERTIFICATE; 84ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 85ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String CLIENT_CERT_PREFIX = KEYSTORE_URI + Credentials.USER_CERTIFICATE; 86ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 87ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String CLIENT_CERT_KEY = "client_cert"; 88ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 89ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String CA_CERT_KEY = "ca_cert"; 90ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 91ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String ENGINE_KEY = "engine"; 92ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 93ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String ENGINE_ID_KEY = "engine_id"; 94ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** @hide */ 95ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String PRIVATE_KEY_ID_KEY = "key_id"; 96ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde 979b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private HashMap<String, String> mFields = new HashMap<String, String>(); 9826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private X509Certificate mCaCert; 9926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private PrivateKey mClientPrivateKey; 10026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private X509Certificate mClientCertificate; 1019b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 1029b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public WifiEnterpriseConfig() { 103e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff // Do not set defaults so that the enterprise fields that are not changed 104e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff // by API are not changed underneath 105e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff // This is essential because an app may not have all fields like password 106e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff // available. It allows modification of subset of fields. 107e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff 1089b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1099b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 1109b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Copy constructor */ 1119b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public WifiEnterpriseConfig(WifiEnterpriseConfig source) { 1129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff for (String key : source.mFields.keySet()) { 1139b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(key, source.mFields.get(key)); 1149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1159b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1169b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 1179b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff @Override 1189b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public int describeContents() { 1199b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return 0; 1209b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1219b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 12286ee9640ee6d6bd9bb655af830eea5515400f25bIrfan Sheriff @Override 1239b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void writeToParcel(Parcel dest, int flags) { 1249b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff dest.writeInt(mFields.size()); 1259b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff for (Map.Entry<String, String> entry : mFields.entrySet()) { 1269b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff dest.writeString(entry.getKey()); 1279b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff dest.writeString(entry.getValue()); 1289b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 12926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 13026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff writeCertificate(dest, mCaCert); 13126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 13226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (mClientPrivateKey != null) { 13326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String algorithm = mClientPrivateKey.getAlgorithm(); 13426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff byte[] userKeyBytes = mClientPrivateKey.getEncoded(); 13526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeInt(userKeyBytes.length); 13626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeByteArray(userKeyBytes); 13726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeString(algorithm); 13826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } else { 13926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeInt(0); 14026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 14126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 14226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff writeCertificate(dest, mClientCertificate); 14326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 14426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 14526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private void writeCertificate(Parcel dest, X509Certificate cert) { 14626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (cert != null) { 14726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff try { 14826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff byte[] certBytes = cert.getEncoded(); 14926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeInt(certBytes.length); 15026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeByteArray(certBytes); 15126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } catch (CertificateEncodingException e) { 15226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeInt(0); 15326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 15426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } else { 15526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff dest.writeInt(0); 15626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 1579b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1589b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 1599b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final Creator<WifiEnterpriseConfig> CREATOR = 1609b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff new Creator<WifiEnterpriseConfig>() { 1619b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public WifiEnterpriseConfig createFromParcel(Parcel in) { 1629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); 1639b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff int count = in.readInt(); 1649b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff for (int i = 0; i < count; i++) { 1659b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff String key = in.readString(); 1669b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff String value = in.readString(); 1679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff enterpriseConfig.mFields.put(key, value); 1689b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 16926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 17026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff enterpriseConfig.mCaCert = readCertificate(in); 17126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 17226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff PrivateKey userKey = null; 17326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff int len = in.readInt(); 17426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (len > 0) { 17526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff try { 17626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff byte[] bytes = new byte[len]; 17726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff in.readByteArray(bytes); 17826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String algorithm = in.readString(); 17926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff KeyFactory keyFactory = KeyFactory.getInstance(algorithm); 18026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff userKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(bytes)); 18126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } catch (NoSuchAlgorithmException e) { 18226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff userKey = null; 18326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } catch (InvalidKeySpecException e) { 18426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff userKey = null; 18526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 18626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 18726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 18826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff enterpriseConfig.mClientPrivateKey = userKey; 18926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff enterpriseConfig.mClientCertificate = readCertificate(in); 1909b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return enterpriseConfig; 1919b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 1929b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 19326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff private X509Certificate readCertificate(Parcel in) { 19426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff X509Certificate cert = null; 19526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff int len = in.readInt(); 19626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (len > 0) { 19726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff try { 19826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff byte[] bytes = new byte[len]; 19926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff in.readByteArray(bytes); 20026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff CertificateFactory cFactory = CertificateFactory.getInstance("X.509"); 20126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff cert = (X509Certificate) cFactory 20226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff .generateCertificate(new ByteArrayInputStream(bytes)); 20326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } catch (CertificateException e) { 20426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff cert = null; 20526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 20626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 20726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return cert; 20826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 20926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 2109b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public WifiEnterpriseConfig[] newArray(int size) { 2119b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return new WifiEnterpriseConfig[size]; 2129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2139b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff }; 2149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 215fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** The Extensible Authentication Protocol method used */ 2169b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final class Eap { 217fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** No EAP method used. Represents an empty config */ 218e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff public static final int NONE = -1; 219fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** Protected EAP */ 2209b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int PEAP = 0; 221fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** EAP-Transport Layer Security */ 2229b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int TLS = 1; 223fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** EAP-Tunneled Transport Layer Security */ 2249b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int TTLS = 2; 225fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** EAP-Password */ 2269b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int PWD = 3; 2277fee7232ee2ae45fb3cd4fcce314e8f1101ae8dbRoger Chang /** EAP-Subscriber Identity Module */ 2287fee7232ee2ae45fb3cd4fcce314e8f1101ae8dbRoger Chang public static final int SIM = 4; 2297fee7232ee2ae45fb3cd4fcce314e8f1101ae8dbRoger Chang /** EAP-Authentication and Key Agreement */ 2307fee7232ee2ae45fb3cd4fcce314e8f1101ae8dbRoger Chang public static final int AKA = 5; 2319b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** @hide */ 2327fee7232ee2ae45fb3cd4fcce314e8f1101ae8dbRoger Chang public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA" }; 23340843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff 23440843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff /** Prevent initialization */ 23540843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff private Eap() {} 2369b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2379b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 238fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** The inner authentication method used */ 2399b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final class Phase2 { 2409b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int NONE = 0; 241fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** Password Authentication Protocol */ 2429b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int PAP = 1; 243fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** Microsoft Challenge Handshake Authentication Protocol */ 2449b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int MSCHAP = 2; 245fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** Microsoft Challenge Handshake Authentication Protocol v2 */ 2469b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int MSCHAPV2 = 3; 247fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff /** Generic Token Card */ 2489b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public static final int GTC = 4; 2499b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private static final String PREFIX = "auth="; 2509b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** @hide */ 251ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public static final String[] strings = {EMPTY_VALUE, "PAP", "MSCHAP", 252ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde "MSCHAPV2", "GTC" }; 25340843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff 25440843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff /** Prevent initialization */ 25540843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff private Phase2() {} 2569b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2579b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 258ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** Internal use only 259ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde * @hide 260ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde */ 261ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public HashMap<String, String> getFields() { 2629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return mFields; 2639b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2649b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 2659b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 2669b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set the EAP authentication method. 2679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param eapMethod is one {@link Eap#PEAP}, {@link Eap#TLS}, {@link Eap#TTLS} or 2689b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * {@link Eap#PWD} 269fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * @throws IllegalArgumentException on an invalid eap method 2709b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 2719b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setEapMethod(int eapMethod) { 2729b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff switch (eapMethod) { 2739b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Valid methods */ 2749b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Eap.PEAP: 2759b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Eap.PWD: 2769b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Eap.TLS: 2779b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Eap.TTLS: 2787fee7232ee2ae45fb3cd4fcce314e8f1101ae8dbRoger Chang case Eap.SIM: 2797fee7232ee2ae45fb3cd4fcce314e8f1101ae8dbRoger Chang case Eap.AKA: 280ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde mFields.put(EAP_KEY, Eap.strings[eapMethod]); 281ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde mFields.put(OPP_KEY_CACHING, "1"); 2829b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff break; 2839b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff default: 2849b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff throw new IllegalArgumentException("Unknown EAP method"); 2859b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2869b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2879b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 2889b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 2899b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get the eap method. 2909b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return eap method configured 2919b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 2929b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public int getEapMethod() { 293ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde String eapMethod = mFields.get(EAP_KEY); 294e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff return getStringIndex(Eap.strings, eapMethod, Eap.NONE); 2959b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 2969b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 2979b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 2989b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set Phase 2 authentication method. Sets the inner authentication method to be used in 2999b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * phase 2 after setting up a secure channel 3009b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param phase2Method is the inner authentication method and can be one of {@link Phase2#NONE}, 3019b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * {@link Phase2#PAP}, {@link Phase2#MSCHAP}, {@link Phase2#MSCHAPV2}, 3029b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * {@link Phase2#GTC} 303fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * @throws IllegalArgumentException on an invalid phase2 method 3049b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 3059b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3069b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setPhase2Method(int phase2Method) { 3079b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff switch (phase2Method) { 3089b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Phase2.NONE: 309ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde mFields.put(PHASE2_KEY, EMPTY_VALUE); 3109b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff break; 3119b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Valid methods */ 3129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Phase2.PAP: 3139b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Phase2.MSCHAP: 3149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Phase2.MSCHAPV2: 3159b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff case Phase2.GTC: 316ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde mFields.put(PHASE2_KEY, convertToQuotedString( 3179b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff Phase2.PREFIX + Phase2.strings[phase2Method])); 3189b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff break; 3199b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff default: 3209b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff throw new IllegalArgumentException("Unknown Phase 2 method"); 3219b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3229b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3239b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3249b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3259b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get the phase 2 authentication method. 3269b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return a phase 2 method defined at {@link Phase2} 3279b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * */ 3289b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public int getPhase2Method() { 329ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde String phase2Method = removeDoubleQuotes(mFields.get(PHASE2_KEY)); 330e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff // Remove auth= prefix 331e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff if (phase2Method.startsWith(Phase2.PREFIX)) { 332e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff phase2Method = phase2Method.substring(Phase2.PREFIX.length()); 333e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff } 3349b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return getStringIndex(Phase2.strings, phase2Method, Phase2.NONE); 3359b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3369b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3379b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3389b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set the identity 3399b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param identity 3409b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3419b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setIdentity(String identity) { 342ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde setFieldValue(IDENTITY_KEY, identity, ""); 3439b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3449b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3459b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3469b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get the identity 3479b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return the identity 3489b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3499b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public String getIdentity() { 350ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde return getFieldValue(IDENTITY_KEY, ""); 3519b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3529b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3539b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3549b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set anonymous identity. This is used as the unencrypted identity with 3559b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * certain EAP types 3569b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param anonymousIdentity the anonymous identity 3579b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3589b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setAnonymousIdentity(String anonymousIdentity) { 359ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde setFieldValue(ANON_IDENTITY_KEY, anonymousIdentity, ""); 3609b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3619b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Get the anonymous identity 3639b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return anonymous identity 3649b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3659b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public String getAnonymousIdentity() { 366ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde return getFieldValue(ANON_IDENTITY_KEY, ""); 3679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3689b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3699b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 3709b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set the password. 3719b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param password the password 3729b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 3739b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setPassword(String password) { 374ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde setFieldValue(PASSWORD_KEY, password, ""); 3759b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3769b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 3779b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 37840843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff * Get the password. 37940843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff * 38040843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff * Returns locally set password value. For networks fetched from 38140843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff * framework, returns "*". 38240843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff */ 38340843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff public String getPassword() { 384ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde return getFieldValue(PASSWORD_KEY, ""); 38540843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff } 38640843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff 38740843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff /** 3889b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set CA certificate alias. 3899b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 3909b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * <p> See the {@link android.security.KeyChain} for details on installing or choosing 3919b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * a certificate 3929b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * </p> 3939b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param alias identifies the certificate 39426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @hide 3959b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 39626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public void setCaCertificateAlias(String alias) { 397ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde setFieldValue(CA_CERT_KEY, alias, CA_CERT_PREFIX); 3989b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 3999b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 4009b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 4019b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get CA certificate alias 4029b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return alias to the CA certificate 40326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @hide 4049b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 40526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public String getCaCertificateAlias() { 406ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde return getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX); 4079b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 4089b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 4099b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 41026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * Specify a X.509 certificate that identifies the server. 41126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * 41226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * <p>A default name is automatically assigned to the certificate and used 413fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * with this configuration. The framework takes care of installing the 414fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * certificate when the config is saved and removing the certificate when 415fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * the config is removed. 416fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * 41726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @param cert X.509 CA certificate 41826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @throws IllegalArgumentException if not a CA certificate 41926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff */ 42026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public void setCaCertificate(X509Certificate cert) { 4210b4732c2248fa2b92a44f045dfcadb3547076ef4Irfan Sheriff if (cert != null) { 4220b4732c2248fa2b92a44f045dfcadb3547076ef4Irfan Sheriff if (cert.getBasicConstraints() >= 0) { 4230b4732c2248fa2b92a44f045dfcadb3547076ef4Irfan Sheriff mCaCert = cert; 4240b4732c2248fa2b92a44f045dfcadb3547076ef4Irfan Sheriff } else { 4250b4732c2248fa2b92a44f045dfcadb3547076ef4Irfan Sheriff throw new IllegalArgumentException("Not a CA certificate"); 4260b4732c2248fa2b92a44f045dfcadb3547076ef4Irfan Sheriff } 42726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } else { 4280b4732c2248fa2b92a44f045dfcadb3547076ef4Irfan Sheriff mCaCert = null; 42926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 43026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 43126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 43226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff /** 43340843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff * Get CA certificate 43440843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff * @return X.509 CA certificate 43540843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff */ 43640843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff public X509Certificate getCaCertificate() { 43740843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff return mCaCert; 43840843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff } 43940843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff 44040843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff /** 441ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde * @hide 442ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde */ 443ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde public void resetCaCertificate() { 444ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde mCaCert = null; 445ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde } 446ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde 447ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde /** Set Client certificate alias. 4489b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * 4499b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * <p> See the {@link android.security.KeyChain} for details on installing or choosing 4509b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * a certificate 4519b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * </p> 4529b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param alias identifies the certificate 45326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @hide 4549b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 45526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public void setClientCertificateAlias(String alias) { 456ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde setFieldValue(CLIENT_CERT_KEY, alias, CLIENT_CERT_PREFIX); 457ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde setFieldValue(PRIVATE_KEY_ID_KEY, alias, Credentials.USER_PRIVATE_KEY); 4589b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff // Also, set engine parameters 4599b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff if (TextUtils.isEmpty(alias)) { 460ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde mFields.put(ENGINE_KEY, ENGINE_DISABLE); 461ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde mFields.put(ENGINE_ID_KEY, EMPTY_VALUE); 4629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } else { 463ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde mFields.put(ENGINE_KEY, ENGINE_ENABLE); 464ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde mFields.put(ENGINE_ID_KEY, convertToQuotedString(ENGINE_ID_KEYSTORE)); 4659b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 4669b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 4679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 4689b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 4699b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get client certificate alias 4709b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return alias to the client certificate 47126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @hide 4729b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 47326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public String getClientCertificateAlias() { 474ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde return getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX); 4759b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 4769b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 4779b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 47826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * Specify a private key and client certificate for client authorization. 47926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * 48026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * <p>A default name is automatically assigned to the key entry and used 481fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * with this configuration. The framework takes care of installing the 482fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * key entry when the config is saved and removing the key entry when 483fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * the config is removed. 484fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff 48526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @param privateKey 48626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff * @param clientCertificate 487fdc028383a01eaaa9bf93cb5d3ce50bd744eab52Irfan Sheriff * @throws IllegalArgumentException for an invalid key or certificate. 48826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff */ 48926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff public void setClientKeyEntry(PrivateKey privateKey, X509Certificate clientCertificate) { 49026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (clientCertificate != null) { 49126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (clientCertificate.getBasicConstraints() != -1) { 49226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff throw new IllegalArgumentException("Cannot be a CA certificate"); 49326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 49426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (privateKey == null) { 49526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff throw new IllegalArgumentException("Client cert without a private key"); 49626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 49726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (privateKey.getEncoded() == null) { 49826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff throw new IllegalArgumentException("Private key cannot be encoded"); 49926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 50026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 50126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 50226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff mClientPrivateKey = privateKey; 50326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff mClientCertificate = clientCertificate; 50426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 50526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 50640843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff /** 50740843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff * Get client certificate 50840843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff * 50940843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff * @return X.509 client certificate 51040843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff */ 51140843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff public X509Certificate getClientCertificate() { 51240843589c46164c90fde29ad1c58291f17d4d9e6Irfan Sheriff return mClientCertificate; 51326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 51426d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 515ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde /** 516ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde * @hide 517ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde */ 518ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde public void resetClientKeyEntry() { 519ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde mClientPrivateKey = null; 520ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde mClientCertificate = null; 52126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 52226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 523ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde /** 524ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde * @hide 525ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde */ 526ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde public PrivateKey getClientPrivateKey() { 527ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde return mClientPrivateKey; 52826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 52926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 53026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff /** 5319b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Set subject match. This is the substring to be matched against the subject of the 5329b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * authentication server certificate. 5339b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param subjectMatch substring to be matched 5349b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 5359b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public void setSubjectMatch(String subjectMatch) { 536ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde setFieldValue(SUBJECT_MATCH_KEY, subjectMatch, ""); 5379b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 5389b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 5399b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** 5409b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * Get subject match 5419b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return the subject match string 5429b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 5439b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public String getSubjectMatch() { 544ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde return getFieldValue(SUBJECT_MATCH_KEY, ""); 5459b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 5469b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 54726d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff /** See {@link WifiConfiguration#getKeyIdForCredentials} @hide */ 54826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff String getKeyId(WifiEnterpriseConfig current) { 549ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde String eap = mFields.get(EAP_KEY); 550ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde String phase2 = mFields.get(PHASE2_KEY); 55126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 55226d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff // If either eap or phase2 are not initialized, use current config details 55326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (TextUtils.isEmpty((eap))) { 554ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde eap = current.mFields.get(EAP_KEY); 55526d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 55626d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (TextUtils.isEmpty(phase2)) { 557ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde phase2 = current.mFields.get(PHASE2_KEY); 55826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 55926d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff return eap + "_" + phase2; 56026d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff } 56126d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff 5629b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private String removeDoubleQuotes(String string) { 5630b4732c2248fa2b92a44f045dfcadb3547076ef4Irfan Sheriff if (TextUtils.isEmpty(string)) return ""; 5649b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff int length = string.length(); 5659b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff if ((length > 1) && (string.charAt(0) == '"') 5669b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff && (string.charAt(length - 1) == '"')) { 5679b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return string.substring(1, length - 1); 5689b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 5699b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return string; 5709b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 5719b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 5729b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private String convertToQuotedString(String string) { 5739b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return "\"" + string + "\""; 5749b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 5759b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 5769b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Returns the index at which the toBeFound string is found in the array. 5779b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param arr array of strings 5789b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param toBeFound string to be found 5799b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param defaultIndex default index to be returned when string is not found 5809b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return the index into array 5819b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 5829b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff private int getStringIndex(String arr[], String toBeFound, int defaultIndex) { 58326d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff if (TextUtils.isEmpty(toBeFound)) return defaultIndex; 5849b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff for (int i = 0; i < arr.length; i++) { 585e095675c872f40f630aa3f9189eb5c02f3cfee6dIrfan Sheriff if (toBeFound.equals(arr[i])) return i; 5869b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 5879b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return defaultIndex; 5889b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 5899b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 5909b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Returns the field value for the key. 5919b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param key into the hash 5929b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param prefix is the prefix that the value may have 5939b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @return value 594ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde * @hide 5959b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 596ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public String getFieldValue(String key, String prefix) { 5979b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff String value = mFields.get(key); 59826d0076f0dbb021c4e5cc1b37b632b2223fd9278Irfan Sheriff // Uninitialized or known to be empty after reading from supplicant 599ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde if (TextUtils.isEmpty(value) || EMPTY_VALUE.equals(value)) return ""; 600dda5a7152fd6e5933503aba8e8badbbba0631839Vinit Deshapnde 601dda5a7152fd6e5933503aba8e8badbbba0631839Vinit Deshapnde value = removeDoubleQuotes(value); 602dda5a7152fd6e5933503aba8e8badbbba0631839Vinit Deshapnde if (value.startsWith(prefix)) { 603dda5a7152fd6e5933503aba8e8badbbba0631839Vinit Deshapnde return value.substring(prefix.length()); 604dda5a7152fd6e5933503aba8e8badbbba0631839Vinit Deshapnde } else { 605dda5a7152fd6e5933503aba8e8badbbba0631839Vinit Deshapnde return value; 606dda5a7152fd6e5933503aba8e8badbbba0631839Vinit Deshapnde } 6079b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6089b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 6099b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff /** Set a value with an optional prefix at key 6109b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param key into the hash 6119b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param value to be set 6129b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff * @param prefix an optional value to be prefixed to actual value 613ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde * @hide 6149b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff */ 615ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde public void setFieldValue(String key, String value, String prefix) { 6169b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff if (TextUtils.isEmpty(value)) { 617ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde mFields.put(key, EMPTY_VALUE); 6189b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } else { 6199b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff mFields.put(key, convertToQuotedString(prefix + value)); 6209b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6219b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6229b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff 623ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde 624ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde /** Set a value with an optional prefix at key 625ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde * @param key into the hash 626ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde * @param value to be set 627ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde * @param prefix an optional value to be prefixed to actual value 628ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde * @hide 629ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde */ 630ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde public void setFieldValue(String key, String value) { 631ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde if (TextUtils.isEmpty(value)) { 632ffadfb9ffdced62db215319d3edc7717802088fbVinit Deshapnde mFields.put(key, EMPTY_VALUE); 633ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde } else { 634ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde mFields.put(key, convertToQuotedString(value)); 635ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde } 636ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde } 637ade8de3c4a021d6b0e753d77be148236af5f39efVinit Deshapnde 6389b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff @Override 6399b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff public String toString() { 6409b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff StringBuffer sb = new StringBuffer(); 6419b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff for (String key : mFields.keySet()) { 6429b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff sb.append(key).append(" ").append(mFields.get(key)).append("\n"); 6439b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6449b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff return sb.toString(); 6459b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff } 6469b81319002634cf7118055f7aafaa26c27d4e5e8Irfan Sheriff} 647