1ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpackage com.android.hotspot2; 2ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 3ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.content.Context; 4ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.content.Intent; 5ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.net.CaptivePortal; 6ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.net.ConnectivityManager; 7ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.net.ICaptivePortal; 8ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.net.Network; 9ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.net.wifi.WifiConfiguration; 10ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.net.wifi.WifiEnterpriseConfig; 11ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.net.wifi.WifiInfo; 12ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.net.wifi.WifiManager; 13ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.util.Log; 14ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 15ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.configparse.ConfigBuilder; 16ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.omadm.MOManager; 17ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.omadm.MOTree; 18ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.omadm.OMAConstants; 19ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.omadm.OMAException; 20ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.omadm.OMAParser; 21ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.osu.OSUCertType; 22ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.osu.OSUInfo; 23ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.osu.OSUManager; 24ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.osu.commands.MOData; 25ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.pps.HomeSP; 26ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 27ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport org.xml.sax.SAXException; 28ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 29ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.io.IOException; 30ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.net.URL; 31ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.security.GeneralSecurityException; 32ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.security.PrivateKey; 33ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.security.cert.X509Certificate; 34ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.ArrayList; 35ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Collection; 36ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.HashMap; 37ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.List; 38ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Map; 39ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 40ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpublic class WifiNetworkAdapter { 41ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final Context mContext; 42ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final OSUManager mOSUManager; 43ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final Map<String, PasspointConfig> mPasspointConfigs = new HashMap<>(); 44ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 45ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private static class PasspointConfig { 46ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final WifiConfiguration mWifiConfiguration; 47ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final MOTree mMOTree; 48ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private final HomeSP mHomeSP; 49ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 50ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private PasspointConfig(WifiConfiguration config) throws IOException, SAXException { 51ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mWifiConfiguration = config; 52ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist OMAParser omaParser = new OMAParser(); 53ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mMOTree = omaParser.parse(config.getMoTree(), OMAConstants.PPS_URN); 54ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist List<HomeSP> spList = MOManager.buildSPs(mMOTree); 55ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (spList.size() != 1) { 56ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throw new OMAException("Expected exactly one HomeSP, got " + spList.size()); 57ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 58ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mHomeSP = spList.iterator().next(); 59ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 60ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 61ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public WifiConfiguration getWifiConfiguration() { 62ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return mWifiConfiguration; 63ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 64ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 65ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public HomeSP getHomeSP() { 66ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return mHomeSP; 67ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 68ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 69ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public MOTree getmMOTree() { 70ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return mMOTree; 71ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 72ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 73ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 74ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public WifiNetworkAdapter(Context context, OSUManager osuManager) { 75ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mOSUManager = osuManager; 76ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mContext = context; 77ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 78ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 79ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void initialize() { 80ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist loadAllSps(); 81ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 82ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 83ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void networkConfigChange(WifiConfiguration configuration) { 84ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist loadAllSps(); 85ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 86ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 87ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private void loadAllSps() { 88ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.d(OSUManager.TAG, "Loading all SPs"); 89ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 90ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist for (WifiConfiguration config : wifiManager.getPrivilegedConfiguredNetworks()) { 91ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist String moTree = config.getMoTree(); 92ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (moTree != null) { 93ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist try { 94ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mPasspointConfigs.put(config.FQDN, new PasspointConfig(config)); 95ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } catch (IOException | SAXException e) { 96ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.w(OSUManager.TAG, "Failed to parse MO: " + e); 97ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 98ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 99ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 100ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 101ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 102ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public Collection<HomeSP> getLoadedSPs() { 103ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist List<HomeSP> homeSPs = new ArrayList<>(); 104ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist for (PasspointConfig config : mPasspointConfigs.values()) { 105ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist homeSPs.add(config.getHomeSP()); 106ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 107ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return homeSPs; 108ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 109ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 110ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public MOTree getMOTree(HomeSP homeSP) { 111ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist PasspointConfig config = mPasspointConfigs.get(homeSP.getFQDN()); 112ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return config != null ? config.getmMOTree() : null; 113ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 114ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 115ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void launchBrowser(URL target, Network network, URL endRedirect) { 116ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.d(OSUManager.TAG, "Browser to " + target + ", land at " + endRedirect); 117ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 118ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist final Intent intent = new Intent( 119ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN); 120ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist intent.putExtra(ConnectivityManager.EXTRA_NETWORK, network); 121ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL, 122ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist new CaptivePortal(new ICaptivePortal.Stub() { 123ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 124ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void appResponse(int response) { 125ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 126ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist })); 127ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist //intent.setData(Uri.parse(target.toString())); !!! Doesn't work! 128ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, target.toString()); 129ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist intent.setFlags( 130ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); 131ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mContext.startActivity(intent); 132ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 133ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 134ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public HomeSP addSP(MOTree instanceTree) throws IOException, SAXException { 135ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 136ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist String xml = instanceTree.toXml(); 137ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.addPasspointManagementObject(xml); 138ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return MOManager.buildSP(xml); 139ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 140ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 141ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void removeSP(String fqdn) throws IOException { 142ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 143ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 144ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 145ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public HomeSP modifySP(HomeSP homeSP, Collection<MOData> mods) 146ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throws IOException { 147ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 148ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 149ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 150ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 151ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public Network getCurrentNetwork() { 152ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 153ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return wifiManager.getCurrentNetwork(); 154ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 155ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 156ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public WifiConfiguration getActiveWifiConfig() { 157ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiInfo wifiInfo = getConnectionInfo(); 158ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (wifiInfo == null) { 159ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 160ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 161ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 162ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist for (WifiConfiguration config : wifiManager.getConfiguredNetworks()) { 163ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (config.networkId == wifiInfo.getNetworkId()) { 164ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return config; 165ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 166ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 167ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 168ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 169ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 170ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public WifiInfo getConnectionInfo() { 171ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 172ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return wifiManager.getConnectionInfo(); 173ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 174ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 175ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public PasspointMatch matchProviderWithCurrentNetwork(String fqdn) { 176ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 177ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int ordinal = wifiManager.matchProviderWithCurrentNetwork(fqdn); 178ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return ordinal >= 0 && ordinal < PasspointMatch.values().length ? 179ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist PasspointMatch.values()[ordinal] : null; 180ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 181ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 182ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public WifiConfiguration getWifiConfig(HomeSP homeSP) { 183ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist PasspointConfig passpointConfig = mPasspointConfigs.get(homeSP.getFQDN()); 184ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return passpointConfig != null ? passpointConfig.getWifiConfiguration() : null; 185ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 186ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 187ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public WifiConfiguration getActivePasspointNetwork() { 188ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist PasspointConfig passpointConfig = getActivePasspointConfig(); 189ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return passpointConfig != null ? passpointConfig.getWifiConfiguration() : null; 190ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 191ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 192ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private PasspointConfig getActivePasspointConfig() { 193ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiInfo wifiInfo = getConnectionInfo(); 194ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (wifiInfo == null) { 195ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 196ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 197ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 198ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist for (PasspointConfig passpointConfig : mPasspointConfigs.values()) { 199ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (passpointConfig.getWifiConfiguration().networkId == wifiInfo.getNetworkId()) { 200ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return passpointConfig; 201ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 202ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 203ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 204ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 205ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 206ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public HomeSP getCurrentSP() { 207ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist PasspointConfig passpointConfig = getActivePasspointConfig(); 208ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return passpointConfig != null ? passpointConfig.getHomeSP() : null; 209ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 210ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 211ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void doIconQuery(long bssid, String fileName) { 212ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 213ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.d("ZXZ", String.format("Icon query for %012x '%s'", bssid, fileName)); 214ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.queryPasspointIcon(bssid, fileName); 215ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 216ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 217ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public Integer addNetwork(HomeSP homeSP, Map<OSUCertType, List<X509Certificate>> certs, 218ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist PrivateKey privateKey, Network osuNetwork) 219ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throws IOException, GeneralSecurityException { 220ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 221ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist List<X509Certificate> aaaTrust = certs.get(OSUCertType.AAA); 222ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (aaaTrust.isEmpty()) { 223ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist aaaTrust = certs.get(OSUCertType.CA); // Get the CAs from the EST flow. 224ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 225ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 226ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiConfiguration config = ConfigBuilder.buildConfig(homeSP, 227ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist aaaTrust.iterator().next(), 228ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist certs.get(OSUCertType.Client), privateKey); 229ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 230ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 231ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int nwkId = wifiManager.addNetwork(config); 232ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist boolean saved = false; 233ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (nwkId >= 0) { 234ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist saved = wifiManager.saveConfiguration(); 235ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 236ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.d(OSUManager.TAG, "Wifi configuration " + nwkId + 237ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist " " + (saved ? "saved" : "not saved")); 238ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 239ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (saved) { 240ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist reconnect(osuNetwork, nwkId); 241ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return nwkId; 242ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } else { 243ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 244ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 245ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 246ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 247ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void updateNetwork(HomeSP homeSP, X509Certificate caCert, 248ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist List<X509Certificate> clientCerts, PrivateKey privateKey) 249ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throws IOException, GeneralSecurityException { 250ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 251ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiConfiguration config = getWifiConfig(homeSP); 252ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (config == null) { 253ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throw new IOException("Failed to find matching network config"); 254ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 255ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.d(OSUManager.TAG, "Found matching config " + config.networkId + ", updating"); 256ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 257ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig; 258ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiConfiguration newConfig = ConfigBuilder.buildConfig(homeSP, 259ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist caCert != null ? caCert : enterpriseConfig.getCaCertificate(), 260ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist clientCerts, privateKey); 261ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist newConfig.networkId = config.networkId; 262ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 263ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 264ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.save(newConfig, null); 265ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.saveConfiguration(); 266ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 267ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 268ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist /** 269ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * Connect to an OSU provisioning network. The connection should not bring down other existing 270ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * connection and the network should not be made the default network since the connection 271ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * is solely for sign up and is neither intended for nor likely provides access to any 272ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * generic resources. 273ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * 274ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * @param osuInfo The OSU info object that defines the parameters for the network. An OSU 275ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * network is either an open network, or, if the OSU NAI is set, an "OSEN" 276ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * network, which is an anonymous EAP-TLS network with special keys. 277ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * @param info An opaque string that is passed on to any user notification. The string is used 278ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * for the name of the service provider. 279ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * @return an Integer holding the network-id of the just added network configuration, or null 280ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * if the network existed prior to this call (was not added by the OSU infrastructure). 281ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * The value will be used at the end of the OSU flow to delete the network as applicable. 282ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * @throws IOException Issues: 283ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * 1. The network id is not returned. addNetwork cannot be called from here since the method 284ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * runs in the context of the app and doesn't have the appropriate permission. 285ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * 2. The connection is not immediately usable if the network was not previously selected 286ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * manually. 287ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist */ 288ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public Integer connect(OSUInfo osuInfo, final String info) throws IOException { 289ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 290ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 291ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiConfiguration config = new WifiConfiguration(); 292ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist config.SSID = '"' + osuInfo.getSSID() + '"'; 293ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (osuInfo.getOSUBssid() != 0) { 294ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist config.BSSID = Utils.macToString(osuInfo.getOSUBssid()); 295ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.d(OSUManager.TAG, String.format("Setting BSSID of '%s' to %012x", 296ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist osuInfo.getSSID(), osuInfo.getOSUBssid())); 297ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 298ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 299ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (osuInfo.getOSUProvider().getOsuNai() == null) { 300ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 301ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } else { 302ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OSEN); 303ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist config.allowedProtocols.set(WifiConfiguration.Protocol.OSEN); 304ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); 305ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GTK_NOT_USED); 306ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist config.enterpriseConfig = new WifiEnterpriseConfig(); 307ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.UNAUTH_TLS); 308ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist config.enterpriseConfig.setIdentity(osuInfo.getOSUProvider().getOsuNai()); 309ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist // !!! OSEN CA Cert??? 310ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 311ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 312ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int networkId = wifiManager.addNetwork(config); 313ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (wifiManager.enableNetwork(networkId, true)) { 314ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return networkId; 315ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } else { 316ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 317ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 318ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 319ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist /* sequence of addNetwork(), enableNetwork(), saveConfiguration() and reconnect() 320ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.connect(config, new WifiManager.ActionListener() { 321ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 322ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void onSuccess() { 323ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist // Connection event comes from network change intent registered in initialize 324ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 325ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 326ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 327ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void onFailure(int reason) { 328ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mOSUManager.notifyUser(OSUOperationStatus.ProvisioningFailure, 329ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist "Cannot connect to OSU network: " + reason, info); 330ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 331ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist }); 332ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 333ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 334ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist /* 335ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist try { 336ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist int nwkID = wifiManager.addOrUpdateOSUNetwork(config); 337ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (nwkID == WifiConfiguration.INVALID_NETWORK_ID) { 338ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist throw new IOException("Failed to add OSU network"); 339ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 340ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.enableNetwork(nwkID, false); 341ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.reconnect(); 342ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return nwkID; 343ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 344ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist catch (SecurityException se) { 345ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist Log.d("ZXZ", "Blah: " + se, se); 346ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.connect(config, new WifiManager.ActionListener() { 347ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 348ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void onSuccess() { 349ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist // Connection event comes from network change intent registered in initialize 350ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 351ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 352ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist @Override 353ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void onFailure(int reason) { 354ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist mOSUManager.notifyUser(OSUOperationStatus.ProvisioningFailure, 355ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist "Cannot connect to OSU network: " + reason, info); 356ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 357ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist }); 358ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist return null; 359ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 360ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist */ 361ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 362ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 363ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist private void reconnect(Network osuNetwork, int newNwkId) { 364ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 365ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (osuNetwork != null) { 366ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.disableNetwork(osuNetwork.netId); 367ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 368ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist if (newNwkId != WifiConfiguration.INVALID_NETWORK_ID) { 369ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.enableNetwork(newNwkId, true); 370ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 371ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 372ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 373ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void deleteNetwork(int id) { 374ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 375ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.disableNetwork(id); 376ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist wifiManager.forget(id, null); 377ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 378ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 379ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist /** 380ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * Set the re-authentication hold off time for the current network 381ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * 382ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * @param holdoff hold off time in milliseconds 383ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * @param ess set if the hold off pertains to an ESS rather than a BSS 384ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist */ 385ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist public void setHoldoffTime(long holdoff, boolean ess) { 386ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist 387ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist } 388ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist} 389