package de.tum.in.tumcampusapp.managers; import android.annotation.TargetApi; import android.content.Context; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.GroupCipher; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiConfiguration.PairwiseCipher; import android.net.wifi.WifiConfiguration.Protocol; import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiManager; import android.os.Build; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.List; import de.tum.in.tumcampusapp.R; import de.tum.in.tumcampusapp.auxiliary.Utils; /** * Eduroam manager, manages connecting to eduroam wifi network */ public class EduroamManager { public static final String NETWORK_SSID = "eduroam"; public static final String RADIUS_DNS = "radius.lrz.de"; private static final String INT_PHASE2 = "phase2"; private static final String INT_PASSWORD = "password"; private static final String INT_IDENTITY = "identity"; private static final String INT_EAP = "eap"; private static final String INT_CA_CERT = "ca_cert"; private static final String INT_ANONYMOUS_IDENTITY = "anonymous_identity"; private static final String INT_ENTERPRISE_FIELD_NAME = "android.net.wifi.WifiConfiguration$EnterpriseField"; private final Context mContext; public EduroamManager(Context context) { mContext = context; } /** * Tests if eduroam has already been setup * * @return true if eduroam is already setup, false otherwise */ static public WifiConfiguration getEduroamConfig(Context c) { WifiManager wifiManager = (WifiManager) c.getApplicationContext().getSystemService(Context.WIFI_SERVICE); List<WifiConfiguration> list = wifiManager.getConfiguredNetworks(); //We didn't get a list, so maybe theres no wifi? if (list == null) { return null; } for (WifiConfiguration config : list) { if (config.SSID != null && config.SSID.equals("\"" + NETWORK_SSID + "\"")) { return config; } } return null; } /** * Configures eduroam wifi connection * * @param lrzId User's LRZ-ID * @param networkPass User's lrz password * @return Returns true if configuration was successful, false otherwise */ public boolean configureEduroam(String lrzId, String networkPass) { // Configure Wifi boolean update = true; WifiConfiguration conf = getEduroamConfig(mContext); if (conf == null) { update = false; conf = new WifiConfiguration(); } conf.SSID = "\"" + NETWORK_SSID + "\""; conf.allowedKeyManagement.set(KeyMgmt.WPA_EAP); conf.allowedKeyManagement.set(KeyMgmt.IEEE8021X); conf.allowedGroupCiphers.set(GroupCipher.TKIP); conf.allowedGroupCiphers.set(GroupCipher.CCMP); conf.allowedGroupCiphers.set(GroupCipher.WEP40); conf.allowedGroupCiphers.set(GroupCipher.WEP104); conf.allowedPairwiseCiphers.set(PairwiseCipher.CCMP); conf.allowedPairwiseCiphers.set(PairwiseCipher.TKIP); conf.allowedProtocols.set(Protocol.RSN); conf.status = WifiConfiguration.Status.ENABLED; if (Build.VERSION.SDK_INT >= 18) { setupEnterpriseConfigAPI18(conf, lrzId, networkPass); } else { if (!setupEnterpriseConfigOld(conf, lrzId, networkPass)) { return false; } } // Add eduroam to wifi networks WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE); int networkId; if (update) { networkId = wifiManager.updateNetwork(conf); Utils.log("deleted " + conf.networkId); } else { networkId = wifiManager.addNetwork(conf); } Utils.log("added " + networkId); //Check if update successful if (networkId == -1) { return false; } //Save, enable and exit wifiManager.saveConfiguration(); wifiManager.enableNetwork(networkId, true); return true; } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) private void setupEnterpriseConfigAPI18(WifiConfiguration conf, String lrzId, String networkPass) { conf.enterpriseConfig.setIdentity(lrzId + "@eduroam.mwn.de"); conf.enterpriseConfig.setPassword(networkPass); conf.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP); conf.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2); conf.enterpriseConfig.setAnonymousIdentity("anonymous@mwn.de"); // Install certificate X509Certificate cert; try { InputStream is = mContext.getResources().openRawResource(R.raw.rootcert); CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); cert = (X509Certificate) certFactory.generateCertificate(is); } catch (CertificateException e) { Utils.log(e); throw new AssertionError("Certificate corrupt!"); } conf.enterpriseConfig.setCaCertificate(cert); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { setSubjectMatchAPI23(conf); } setSubjectMatch18To23(conf); //Set both just to be sure } @TargetApi(Build.VERSION_CODES.M) private void setSubjectMatchAPI23(WifiConfiguration conf) { conf.enterpriseConfig.setDomainSuffixMatch(RADIUS_DNS); conf.enterpriseConfig.setAltSubjectMatch("DNS:" + RADIUS_DNS); } @TargetApi(18) @SuppressWarnings("deprecation") private void setSubjectMatch18To23(WifiConfiguration conf) { conf.enterpriseConfig.setSubjectMatch(RADIUS_DNS); } private boolean setupEnterpriseConfigOld(WifiConfiguration conf, String lrzId, String networkPass) { try { // Get class instance for enterprise field class and than find setValue Method Method wcefSetValue = null; Class<?>[] wcClasses = WifiConfiguration.class.getClasses(); for (Class<?> wcClass : wcClasses) { if (wcClass.getName().equals(INT_ENTERPRISE_FIELD_NAME)) { for (Method m : wcClass.getMethods()) { if (m.getName().trim().equals("setValue")) { wcefSetValue = m; break; } } break; } } if (wcefSetValue == null) { return false; } Field[] wcefFields = WifiConfiguration.class.getFields(); for (Field wcefField : wcefFields) { if (wcefField.getName().trim().equals(INT_ANONYMOUS_IDENTITY)) { wcefSetValue.invoke(wcefField.get(conf), "anonymous@mwn.de"); } else if (wcefField.getName().trim().equals(INT_CA_CERT)) { wcefSetValue.invoke(wcefField.get(conf), "keystore://CACERT_eduroam"); } else if (wcefField.getName().trim().equals(INT_EAP)) { wcefSetValue.invoke(wcefField.get(conf), "PEAP"); } else if (wcefField.getName().trim().equals(INT_IDENTITY)) { wcefSetValue.invoke(wcefField.get(conf), lrzId + "@eduroam.mwn.de"); } else if (wcefField.getName().trim().equals(INT_PASSWORD)) { wcefSetValue.invoke(wcefField.get(conf), networkPass); } else if (wcefField.getName().trim().equals(INT_PHASE2)) { wcefSetValue.invoke(wcefField.get(conf), "MSCHAPV2"); } } } catch (Exception e) { Utils.log(e); return false; } return true; } }