1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wifi.util;
18
19import android.net.wifi.ScanResult;
20import android.net.wifi.WifiConfiguration;
21import android.text.TextUtils;
22
23import com.android.internal.annotations.VisibleForTesting;
24import com.android.server.wifi.ScanDetail;
25import com.android.server.wifi.WifiConfigurationUtil;
26import com.android.server.wifi.hotspot2.NetworkDetail;
27
28/**
29 * Scan result utility for any {@link ScanResult} related operations.
30 * Currently contains:
31 *   > Helper method for converting a ScanResult to a ScanDetail.
32 *     Only fields that are supported in ScanResult are copied.
33 *   > Helper methods to identify the encryption of a ScanResult.
34 */
35public class ScanResultUtil {
36    private ScanResultUtil() { /* not constructable */ }
37
38    /**
39     * This method should only be used when the informationElements field in the provided scan
40     * result is filled in with the IEs from the beacon.
41     */
42    public static ScanDetail toScanDetail(ScanResult scanResult) {
43        NetworkDetail networkDetail = new NetworkDetail(scanResult.BSSID,
44                scanResult.informationElements, scanResult.anqpLines, scanResult.frequency);
45        return new ScanDetail(scanResult, networkDetail);
46    }
47
48    /**
49     * Helper method to check if the provided |scanResult| corresponds to a PSK network or not.
50     * This checks if the provided capabilities string contains PSK encryption type or not.
51     */
52    public static boolean isScanResultForPskNetwork(ScanResult scanResult) {
53        return scanResult.capabilities.contains("PSK");
54    }
55
56    /**
57     * Helper method to check if the provided |scanResult| corresponds to a EAP network or not.
58     * This checks if the provided capabilities string contains EAP encryption type or not.
59     */
60    public static boolean isScanResultForEapNetwork(ScanResult scanResult) {
61        return scanResult.capabilities.contains("EAP");
62    }
63
64    /**
65     * Helper method to check if the provided |scanResult| corresponds to a WEP network or not.
66     * This checks if the provided capabilities string contains WEP encryption type or not.
67     */
68    public static boolean isScanResultForWepNetwork(ScanResult scanResult) {
69        return scanResult.capabilities.contains("WEP");
70    }
71
72    /**
73     * Helper method to check if the provided |scanResult| corresponds to an open network or not.
74     * This checks if the provided capabilities string does not contain either of WEP, PSK or EAP
75     * encryption types or not.
76     */
77    public static boolean isScanResultForOpenNetwork(ScanResult scanResult) {
78        return !(isScanResultForWepNetwork(scanResult) || isScanResultForPskNetwork(scanResult)
79                || isScanResultForEapNetwork(scanResult));
80    }
81
82    /**
83     * Helper method to quote the SSID in Scan result to use for comparing/filling SSID stored in
84     * WifiConfiguration object.
85     */
86    @VisibleForTesting
87    public static String createQuotedSSID(String ssid) {
88        return "\"" + ssid + "\"";
89    }
90
91    /**
92     * Checks if the provided |scanResult| match with the provided |config|. Essentially checks
93     * if the network config and scan result have the same SSID and encryption type.
94     */
95    public static boolean doesScanResultMatchWithNetwork(
96            ScanResult scanResult, WifiConfiguration config) {
97        // Add the double quotes to the scan result SSID for comparison with the network configs.
98        String configSSID = createQuotedSSID(scanResult.SSID);
99        if (TextUtils.equals(config.SSID, configSSID)) {
100            if (ScanResultUtil.isScanResultForPskNetwork(scanResult)
101                    && WifiConfigurationUtil.isConfigForPskNetwork(config)) {
102                return true;
103            }
104            if (ScanResultUtil.isScanResultForEapNetwork(scanResult)
105                    && WifiConfigurationUtil.isConfigForEapNetwork(config)) {
106                return true;
107            }
108            if (ScanResultUtil.isScanResultForWepNetwork(scanResult)
109                    && WifiConfigurationUtil.isConfigForWepNetwork(config)) {
110                return true;
111            }
112            if (ScanResultUtil.isScanResultForOpenNetwork(scanResult)
113                    && WifiConfigurationUtil.isConfigForOpenNetwork(config)) {
114                return true;
115            }
116        }
117        return false;
118    }
119
120    /**
121     * Creates a network configuration object using the provided |scanResult|.
122     * This is used to create ephemeral network configurations.
123     */
124    public static WifiConfiguration createNetworkFromScanResult(ScanResult scanResult) {
125        WifiConfiguration config = new WifiConfiguration();
126        config.SSID = createQuotedSSID(scanResult.SSID);
127        setAllowedKeyManagementFromScanResult(scanResult, config);
128        return config;
129    }
130
131    /**
132     * Sets the {@link WifiConfiguration#allowedKeyManagement} field on the given
133     * {@link WifiConfiguration} based on its corresponding {@link ScanResult}.
134     */
135    public static void setAllowedKeyManagementFromScanResult(ScanResult scanResult,
136            WifiConfiguration config) {
137        if (isScanResultForPskNetwork(scanResult)) {
138            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
139        } else if (isScanResultForEapNetwork(scanResult)) {
140            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
141            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
142        } else if (isScanResultForWepNetwork(scanResult)) {
143            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
144            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
145            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
146        } else {
147            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
148        }
149    }
150}
151