1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.server.wifi;
17 
18 import android.net.wifi.ScanResult;
19 import android.net.wifi.WifiConfiguration;
20 
21 import com.android.server.wifi.util.ScanResultUtil;
22 
23 import java.util.Objects;
24 
25 /**
26  * Class to store the info needed to match a scan result to the provided network configuration.
27  */
28 public class ScanResultMatchInfo {
29     /**
30      * SSID of the network.
31      */
32     public String networkSsid;
33     /**
34      * Security Type of the network.
35      */
36     public @WifiConfiguration.SecurityType int networkType;
37     /**
38      * Special flag for PSK-SAE in transition mode
39      */
40     public boolean pskSaeInTransitionMode;
41     /**
42      * Special flag for OWE in transition mode
43      */
44     public boolean oweInTransitionMode;
45 
46     /**
47      * Fetch network type from network configuration.
48      */
getNetworkType(WifiConfiguration config)49     public static @WifiConfiguration.SecurityType int getNetworkType(WifiConfiguration config) {
50         if (WifiConfigurationUtil.isConfigForSaeNetwork(config)) {
51             return WifiConfiguration.SECURITY_TYPE_SAE;
52         } else if (WifiConfigurationUtil.isConfigForPskNetwork(config)) {
53             return WifiConfiguration.SECURITY_TYPE_PSK;
54         } else if (WifiConfigurationUtil.isConfigForEapNetwork(config)) {
55             return WifiConfiguration.SECURITY_TYPE_EAP;
56         } else if (WifiConfigurationUtil.isConfigForEapSuiteBNetwork(config)) {
57             return WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B;
58         } else if (WifiConfigurationUtil.isConfigForWepNetwork(config)) {
59             return WifiConfiguration.SECURITY_TYPE_WEP;
60         } else if (WifiConfigurationUtil.isConfigForOweNetwork(config)) {
61             return WifiConfiguration.SECURITY_TYPE_OWE;
62         } else if (WifiConfigurationUtil.isConfigForOpenNetwork(config)) {
63             return WifiConfiguration.SECURITY_TYPE_OPEN;
64         }
65         throw new IllegalArgumentException("Invalid WifiConfiguration: " + config);
66     }
67 
68     /**
69      * Get the ScanResultMatchInfo for the given WifiConfiguration
70      */
fromWifiConfiguration(WifiConfiguration config)71     public static ScanResultMatchInfo fromWifiConfiguration(WifiConfiguration config) {
72         ScanResultMatchInfo info = new ScanResultMatchInfo();
73         info.networkSsid = config.SSID;
74         info.networkType = getNetworkType(config);
75         return info;
76     }
77 
78     /**
79      * Fetch network type from scan result.
80      */
getNetworkType(ScanResult scanResult)81     public static @WifiConfiguration.SecurityType int getNetworkType(ScanResult scanResult) {
82         if (ScanResultUtil.isScanResultForSaeNetwork(scanResult)) {
83             return WifiConfiguration.SECURITY_TYPE_SAE;
84         } else if (ScanResultUtil.isScanResultForPskNetwork(scanResult)) {
85             return WifiConfiguration.SECURITY_TYPE_PSK;
86         } else if (ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)) {
87             return WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B;
88         } else if (ScanResultUtil.isScanResultForEapNetwork(scanResult)) {
89             return WifiConfiguration.SECURITY_TYPE_EAP;
90         } else if (ScanResultUtil.isScanResultForWepNetwork(scanResult)) {
91             return WifiConfiguration.SECURITY_TYPE_WEP;
92         } else if (ScanResultUtil.isScanResultForOweNetwork(scanResult)) {
93             return WifiConfiguration.SECURITY_TYPE_OWE;
94         } else if (ScanResultUtil.isScanResultForOpenNetwork(scanResult)) {
95             return WifiConfiguration.SECURITY_TYPE_OPEN;
96         } else {
97             throw new IllegalArgumentException("Invalid ScanResult: " + scanResult);
98         }
99     }
100 
101     /**
102      * Get the ScanResultMatchInfo for the given ScanResult
103      */
fromScanResult(ScanResult scanResult)104     public static ScanResultMatchInfo fromScanResult(ScanResult scanResult) {
105         ScanResultMatchInfo info = new ScanResultMatchInfo();
106         // Scan result ssid's are not quoted, hence add quotes.
107         // TODO: This matching algo works only if the scan result contains a string SSID.
108         // However, according to our public documentation ths {@link WifiConfiguration#SSID} can
109         // either have a hex string or quoted ASCII string SSID.
110         info.networkSsid = ScanResultUtil.createQuotedSSID(scanResult.SSID);
111         info.networkType = getNetworkType(scanResult);
112         info.oweInTransitionMode = false;
113         info.pskSaeInTransitionMode = false;
114         if (info.networkType == WifiConfiguration.SECURITY_TYPE_SAE) {
115             // Note that scan result util will always choose the highest security protocol.
116             info.pskSaeInTransitionMode =
117                     ScanResultUtil.isScanResultForPskSaeTransitionNetwork(scanResult);
118         } else  if (info.networkType == WifiConfiguration.SECURITY_TYPE_OWE) {
119             // Note that scan result util will always choose OWE.
120             info.oweInTransitionMode =
121                     ScanResultUtil.isScanResultForOweTransitionNetwork(scanResult);
122         }
123         return info;
124     }
125 
126     @Override
equals(Object otherObj)127     public boolean equals(Object otherObj) {
128         if (this == otherObj) {
129             return true;
130         } else if (!(otherObj instanceof ScanResultMatchInfo)) {
131             return false;
132         }
133         ScanResultMatchInfo other = (ScanResultMatchInfo) otherObj;
134         if (!Objects.equals(networkSsid, other.networkSsid)) {
135             return false;
136         }
137         boolean networkTypeEquals;
138 
139         // Detect <SSID, PSK+SAE> scan result and say it is equal to <SSID, PSK> configuration
140         if (other.pskSaeInTransitionMode && networkType == WifiConfiguration.SECURITY_TYPE_PSK
141                 || (pskSaeInTransitionMode
142                 && other.networkType == WifiConfiguration.SECURITY_TYPE_PSK)) {
143             networkTypeEquals = true;
144         } else if ((networkType == WifiConfiguration.SECURITY_TYPE_OPEN
145                 && other.oweInTransitionMode) || (oweInTransitionMode
146                 && other.networkType == WifiConfiguration.SECURITY_TYPE_OPEN)) {
147             // Special case we treat Enhanced Open and Open as equals. This is done to support the
148             // case where a saved network is Open but we found an OWE in transition network.
149             networkTypeEquals = true;
150         } else {
151             networkTypeEquals = networkType == other.networkType;
152         }
153         return networkTypeEquals;
154     }
155 
156     @Override
hashCode()157     public int hashCode() {
158         return Objects.hash(networkSsid);
159     }
160 
161     @Override
toString()162     public String toString() {
163         return "ScanResultMatchInfo: ssid: " + networkSsid + ", type: " + networkType;
164     }
165 }
166