1 /* 2 * Copyright (C) 2021 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 17 package com.android.server.wifi; 18 19 import static com.android.server.wifi.InsecureEapNetworkHandler.TOFU_ANONYMOUS_IDENTITY; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assume.assumeFalse; 25 import static org.junit.Assume.assumeTrue; 26 import static org.mockito.Mockito.any; 27 import static org.mockito.Mockito.anyBoolean; 28 import static org.mockito.Mockito.anyInt; 29 import static org.mockito.Mockito.anyString; 30 import static org.mockito.Mockito.argThat; 31 import static org.mockito.Mockito.atLeastOnce; 32 import static org.mockito.Mockito.eq; 33 import static org.mockito.Mockito.mock; 34 import static org.mockito.Mockito.never; 35 import static org.mockito.Mockito.spy; 36 import static org.mockito.Mockito.validateMockitoUsage; 37 import static org.mockito.Mockito.verify; 38 import static org.mockito.Mockito.when; 39 import static org.mockito.Mockito.withSettings; 40 41 import android.app.Notification; 42 import android.content.BroadcastReceiver; 43 import android.content.Intent; 44 import android.net.wifi.WifiConfiguration; 45 import android.net.wifi.WifiContext; 46 import android.net.wifi.WifiEnterpriseConfig; 47 import android.os.Handler; 48 import android.os.test.TestLooper; 49 import android.text.TextUtils; 50 import android.text.format.DateFormat; 51 52 import androidx.test.filters.SmallTest; 53 54 import com.android.dx.mockito.inline.extended.ExtendedMockito; 55 import com.android.modules.utils.build.SdkLevel; 56 import com.android.server.wifi.util.CertificateSubjectInfo; 57 import com.android.wifi.resources.R; 58 59 import org.junit.After; 60 import org.junit.Before; 61 import org.junit.Test; 62 import org.mockito.Answers; 63 import org.mockito.ArgumentCaptor; 64 import org.mockito.Captor; 65 import org.mockito.Mock; 66 import org.mockito.MockitoAnnotations; 67 import org.mockito.MockitoSession; 68 import org.mockito.stubbing.Answer; 69 70 import java.io.ByteArrayInputStream; 71 import java.io.InputStream; 72 import java.security.KeyStore; 73 import java.security.cert.CertificateFactory; 74 import java.security.cert.X509Certificate; 75 import java.util.ArrayList; 76 import java.util.Collections; 77 import java.util.List; 78 79 /** 80 * Unit tests for {@link com.android.server.wifi.InsecureEapNetworkHandlerTest}. 81 */ 82 @SmallTest 83 public class InsecureEapNetworkHandlerTest extends WifiBaseTest { 84 85 private static final int ACTION_ACCEPT = 0; 86 private static final int ACTION_REJECT = 1; 87 private static final int ACTION_TAP = 2; 88 private static final int ACTION_FORGET = 3; 89 private static final String WIFI_IFACE_NAME = "wlan-test-9"; 90 private static final int FRAMEWORK_NETWORK_ID = 2; 91 private static final String TEST_SSID = "\"test_ssid\""; 92 private static final String TEST_IDENTITY = "userid"; 93 private static final String TEST_PASSWORD = "myPassWord!"; 94 private static final String TEST_EXPECTED_SHA_256_SIGNATURE = "54:59:5D:FC:64:9C:17:72:C0:59:" 95 + "9D:25:BD:1F:04:18:E6:00:AB:F4:0A:F0:78:D8:9A:FF:56:C0:7C:89:96:2F"; 96 private static final int TEST_GEN_CA_CERT = 0; 97 private static final int TEST_GEN_CA2_CERT = 1; 98 private static final int TEST_GEN_SERVER_CERT = 2; 99 private static final int TEST_GEN_SELF_SIGNED_CERT = 3; 100 private static final int TEST_GEN_FAKE_CA_CERT = 4; 101 102 private static final String TEST_SERVER_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" 103 + "MIIGPjCCBCagAwIBAgIUN2Ss1JmvjveRe97iWoNh4V+Y5LYwDQYJKoZIhvcNAQEM\n" 104 + "BQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQK\n" 105 + "DBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8\n" 106 + "MDoGA1UEAwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5k\n" 107 + "IGRldmVsb3BtZW50MB4XDTIzMDQxMzAyMTYwMVoXDTQzMDQwODAyMTYwMVowgYMx\n" 108 + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMR0wGwYDVQQKDBRBbmRy\n" 109 + "b2lkIFdpLUZpIFRlc3RlcjEYMBYGA1UECwwPYW5kcm9pZHdpZmkub2VtMSYwJAYD\n" 110 + "VQQDDB1BbmRyb2lkIFdpLUZpIE9FTSBUZXN0IFNlcnZlcjCCAiIwDQYJKoZIhvcN\n" 111 + "AQEBBQADggIPADCCAgoCggIBAKveC9QnsxvM2TMzkUINabtM2Bi5M5gzV4v1MN0h\n" 112 + "n1XjXhfRXwwLMK9xtV05r91YQaOTPkHNgA6nhjmL7agcquGPlR7nuS04oxCaqfo4\n" 113 + "unbroyyqDMaXd8U6B1VlvWSbWAAhBEEAPYDhFXF9V83XHEGcp61Hs4VetGmlC3tW\n" 114 + "W1CLIk+o9JRYsZeK4Q1DurAY7YPU8U84QNxPG7OXg+ensGtspuLLNFEdnd9tSi45\n" 115 + "u5KyPpnSwTdRGSCfMVocxj0EINpdrLnWZyf9NX8Uo7tg/D0TFVBo+MbKjgItIdMg\n" 116 + "STLQwceOdOGHZTPiItzpFcP9EA5ug5gXobPjzDTJO2S3NhUt5NURfGr/wyepxR25\n" 117 + "PDRhBgc/xwc7JrtDGaqmknguZuf7Zai/m4iquC0Wh38bWKms8R0ND/H923aFppxp\n" 118 + "vzX/sWotsTYWiGMehh7v6iwIYADifsXBlJXTUhTZt6cnwttZYfp5oqymCsIhXKVU\n" 119 + "IXOE/PLcU71G9U+jCa7PNs5X5LgqorNPABOpkVL+fDpvopNCdhOEVvwCAIl4tIxl\n" 120 + "M0goFbBmY1wnFFYIUki91UfbeUimCUbBq/RSxuXn3liVB/X+dnyjJ3RnNxJ3Wy1m\n" 121 + "mcHFIVV5VxN6tC7XTXYgZAv0EJGCcVn0RN3ldPWGRLTEIQu7cXRSfqs89N4S31Et\n" 122 + "SjaxAgMBAAGjgZMwgZAwHQYDVR0OBBYEFHh9fcIU3LHamK7PdpasvHmzyRoLMB8G\n" 123 + "A1UdIwQYMBaAFH7ro7AWsBlMNpyRXHGW1hG4c1ocMAkGA1UdEwQCMAAwCwYDVR0P\n" 124 + "BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMCEGA1UdEQQaMBiCFnNlcnZlci5h\n" 125 + "bmRyb2lkd2lmaS5vZW0wDQYJKoZIhvcNAQEMBQADggIBAOIkOLyF8mmYvj8TeM2V\n" 126 + "d4YMj4sWf7L5C2lq9OGBJwZad1xytymWWZ7PpNf1MopabfUzxPjw5EfMC94MJmpf\n" 127 + "gqYOwFAye5fXQ8CLC39tb681u44tv/B5vqP74TKVhCR8O1YCsIssa8t8e5nIwcYr\n" 128 + "fj3SBu7iOLtL7zjfEXFo3oSEwVYnvS3lhZL8NTrrHscy/ZLFE3nGRq2d3jPbyuoH\n" 129 + "1FJwenxnD6a/AztERPkRNGk2oSFkWecNU9PC9w3bI5wF4I2AIaFgBOj20S7pVtq7\n" 130 + "7nhKnQFrZYVeWbqbInQcRAcSopI6D6tB/F/T9R1WCWBxvpwdciv7BeNgOtGKAszA\n" 131 + "z0sOxI6O4U77R+tFeb0vCwC0OhVL3W0zX3Fy2835D/hC2P1jmMBlxLVKYHY48RBC\n" 132 + "sG1I1qAMD4eXle8rG9MkB9cE5KfncjCrzSQjT8gs7QBTafb6B3WDdwzfaCaQTOOF\n" 133 + "Tsyrdq0TTJP71bt5qWTr6UZIBE5Tjel+DPpvQlPZPYygXPrI3WBcT12VLhti0II6\n" 134 + "1jgkS8fPLR0VypHR02V5fqCRmy9ln0rSyHXFwL3JpeXYD92eLOKdS1MhIUN4bDxZ\n" 135 + "fiXXVKpKU4gqqWAan2RjbBzQjsi6Eh3yuDm2SAqNZVacpOt7BIslqEZ+Og6KhTTk\n" 136 + "DCzyEOB87ySrUWu3PN3r2sJN\n" 137 + "-----END CERTIFICATE-----"; 138 139 private static final String TEST_CA_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" 140 + "MIIGADCCA+igAwIBAgIUFkmrYCj/UYNrizDdMATu6dE3lBIwDQYJKoZIhvcNAQEM\n" 141 + "BQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQK\n" 142 + "DBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8\n" 143 + "MDoGA1UEAwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5k\n" 144 + "IGRldmVsb3BtZW50MB4XDTIzMDQxMzAyMTYwMVoXDTQzMDQwODAyMTYwMVowgZcx\n" 145 + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQKDBJBbmRy\n" 146 + "b2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8MDoGA1UE\n" 147 + "AwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5kIGRldmVs\n" 148 + "b3BtZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9JERd2HVp/PI\n" 149 + "3WmaaHDKHDuWZoxUDlyVrTDd1Vu2zhH3A5KJ232QOMxJiLdZ/KxgcpGlAEllijae\n" 150 + "xihxhkHEYr7ff2/p6ZhUWr+0vuk8f4TZsKDAE0SoZoDBHTIbrJf8hHM5/+R//sx1\n" 151 + "/fTf8abOj20zyeWmXqvUNXoVKiRvjiZD69tcRHmfmTOMX0lAirOel8ZwwDFamH8d\n" 152 + "wov0IIyd58m6CV91WnScgg7TOzw/IGpccft73RbDw7cHU5i3G3KhOqamwJbErgya\n" 153 + "x97AsSVCqjBz7rEwm6pHjUagbgVAk9ULmI1McQzMINIrOWRF0Q8awWpvDNwPu86J\n" 154 + "W/LfyzAruWtriimycpl7wv0b/f7JhKerG0+44JUI0sgTz/kobAsU8nfYSyVu8+cX\n" 155 + "HwnDE2jBGB6co2Y00eVKxy6+gWTekpQTyHuPoCieNDukC/38Mj+U0KUZkgGv4CL7\n" 156 + "zaVBGzjSjtnAp47aXciaDvDbpST23ICS7TN5cUnXQ1fWfNUMNkEbIPy2mrlRoCxg\n" 157 + "OJ67UEvGIygE0IUvwDfFvF21+1yKk6D/kU9gMgd6DKtvWj1CIyKXWf+rQ01OHNhX\n" 158 + "YcOTkF5aF2WU558DuS+utGBzXWFsLxqBRe9nDb9W/SlrT2jajfwLelMddvtZmVsY\n" 159 + "NG8IeY8lDs5hcFBvm/BDr0SvBDhs9H0CAwEAAaNCMEAwHQYDVR0OBBYEFH7ro7AW\n" 160 + "sBlMNpyRXHGW1hG4c1ocMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGG\n" 161 + "MA0GCSqGSIb3DQEBDAUAA4ICAQBINF6auWUhCO0l/AqO5pLgOqZ7BjAzHGDNapW+\n" 162 + "3nn2YicDD/X2eJASfsd3jN5JluBlbLqRBBWnIsNG/fyKxY8I4+IrR1x8ovwBjeJ3\n" 163 + "McQeCW2zedluVp2SW3LaNQS+aptXHATJ6O8EOny2LDM+obEtFyLuDC89a1TXjEdj\n" 164 + "XGIYmSJ8RwpKAi4u6ff4jhtNTSEa/eIUE5zUREV0916xtmu5y1vlmsEbpLEquOph\n" 165 + "ZWxpUVTqGEyc0hHaivAWyBG1dtRgov5olzHchM2TsEq/VufiRAw5uzRQ/sAyVjj4\n" 166 + "pcvWnLDLTYk/+uIG1zmbc0rNpAC7b3tplA4OqTtFb3yX0ppPFUg4OaxhMyu4WqS3\n" 167 + "roNiXc8BmtfzMqyWAG21QUfosLa8heiiHgnvkiUa9V2oJ4kWAhOTmLdU70aocu4N\n" 168 + "pcN5jcT5hSl/A91Lvfht0C9BLOrXU+RDCNAVIUnnWSrgduUPTydKVdUkLxau4G/+\n" 169 + "G8fKAyeCouFNq7bp4DEMkgqAWpx96Qe6FLxAS59Ig3tI8MZSieBZezJyjP4GWtuq\n" 170 + "QsnARbwD7z73FWQ+eqXOhkoqDoQc8E2lQGe8OGbacGuUwXo3PUgGaJobz+2Hqa9g\n" 171 + "6AnBkH6AbvooUwSWSCyYIf2LA+GvZotI+PXWuQL7dqWtkaNf98qqfnlZXjp51e+h\n" 172 + "B8nquw==\n" 173 + "-----END CERTIFICATE-----"; 174 175 private static final String TEST_CA2_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" 176 + "MIIGADCCA+igAwIBAgIUGm2nmrZw4ADU7h/TGKd67Uz5bJIwDQYJKoZIhvcNAQEM\n" 177 + "BQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQK\n" 178 + "DBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8\n" 179 + "MDoGA1UEAwwzQW5vdGhlciBBbmRyb2lkIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5k\n" 180 + "IGRldmVsb3BtZW50MB4XDTIzMDQxMzAyMTkxOVoXDTQzMDQwODAyMTkxOVowgZcx\n" 181 + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQKDBJBbmRy\n" 182 + "b2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8MDoGA1UE\n" 183 + "AwwzQW5vdGhlciBBbmRyb2lkIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5kIGRldmVs\n" 184 + "b3BtZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvv7PYhFHK+nC\n" 185 + "KoDiQI7dhDFTNU4RxTTsxMRSt1n/FJGZX/r8nnr76gB+oofFVjKQusYhuquKGPGq\n" 186 + "ZfrfmtsNhcVBMnNRjZkBWpNb3XO+7F+Qd/gT7yoiZ0L3Ef4QMCGqNrf10EWmXvVQ\n" 187 + "tpaM7RrkmlW6Zu2VbfP/iQQ7EVFrFWmnZfkCxpkLT+LK+pxwNxtJz5l7VRYkXelw\n" 188 + "9vFdq81C+obBpLWg62mNVNa25g6y46YrSOPyxhiemiRih+avIZ9Z6/7qRoVu7t8U\n" 189 + "NpxzMdsDL5bJREadsjpQWZr7A+umm0nlod1DB204K18Y5Z4GuOEGifdHIUmb+3c4\n" 190 + "Kz14FzBahyc3xsZL73AsGEVWLHIQQ/kjepomVl8HuSHdgw6SZR30JhWgU/bcVl01\n" 191 + "8qc6qH7x3e64Ip9xHdng42oPJHEKYipRed3AXzlCQ7Lc9MeAeR+nB9JuSNc6HW0L\n" 192 + "eh9Po0cDJa194UfNeqJ7SG2uNpeg/OUbM+M3iO3dmCRcV3GzirbT8eHZk3Cor3gb\n" 193 + "h9AzmJnHyRaRc9Xtj7AE8swJRvAoWVlCzcBcvaLAW0hn2DWXbWXHDf63Q8n5F4J5\n" 194 + "pf//2eXWaOXFLvkm9wYUj6kXOehcibB2O1F1YvqWE3XZ5GTDq/+E5wK55aifq+bz\n" 195 + "l1Mb1ILIB3cEEL9w+0ClHCno+2XGMOkCAwEAAaNCMEAwHQYDVR0OBBYEFH0KeaUK\n" 196 + "koS2PMYfpcanoTkRBTzmMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGG\n" 197 + "MA0GCSqGSIb3DQEBDAUAA4ICAQCnnL83fEA3g8fiJHpeSNSVZ4R3VunQU2BDkwUj\n" 198 + "NgFWPMsZNQcKoChUA5mb8wOM/fk9tdjMsQR5fRO30B94Eoo9NM39HztBcvvLV9i7\n" 199 + "qNQCTjFE7zf4weX6K3tZICR8nZ1Ogccp3itEDkNpOylFLdQxkc29RrKcuculb3PM\n" 200 + "C7IMREKROKFzrAwWkFAaxJGfByTRfjOqWJFgdRq/GHU2yCKkCLN4zRLjr5ZaAk2J\n" 201 + "+8b+Y1/pIW4j2FAB7ebmq0ZbMbdc+EFdVf36WrsWf54L3DsZOuoaC+2wTsyWQ0b/\n" 202 + "8tqJ/XS39I4uo8KpI5//aQpM1usxP0/pWUm9sTXE618Yf2Ynh64eDQHPIAmt+Xoh\n" 203 + "BfIx+nXVkCl4DGGdwvOURUULdHN9wf6YPOXxaMEYxQRGMwmBAlmiDaH41xeaht/A\n" 204 + "+iv3y918rJFDAXWKvGia8oDi1xIL+IDZ1AGVByNp+C/AE5BTV2m9UHZyXsXrMiQA\n" 205 + "ezUrVpiWB6h4C4rUuaucQv1gO6gEPZGEDdvIG8TGJg8wvLL0oZiyaL3gQxlGs0CZ\n" 206 + "tbDGqugtlh4RLeJ1N/TTFkLzf4CAgDTxfqhMKXkFvpMvO6ZHOT7xC0sdaD2FbZRj\n" 207 + "h5ziC9nvWEdTA8RLr0i/r5nFb6GsxmEk6NYFmpnyo5pvlxf5xqOhsJZlcKnUJ8SQ\n" 208 + "NIGLmw==\n" 209 + "-----END CERTIFICATE-----"; 210 211 private static final String TEST_SELF_SIGNED_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" 212 + "MIIFxzCCA6+gAwIBAgIUB8Kqwhhhs1liW23ve7pZsFlv0zAwDQYJKoZIhvcNAQEM\n" 213 + "BQAwezELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExGzAZBgNVBAoM\n" 214 + "EkFuZHJvaWQgV2ktRmkgVGVzdDEYMBYGA1UECwwPYW5kcm9pZHdpZmkuZGV2MSAw\n" 215 + "HgYDVQQDDBdTZWxmLXNpZ25lZCBjZXJ0aWZpY2F0ZTAeFw0yMzA0MTMwMjE0MTda\n" 216 + "Fw00MzA0MDgwMjE0MTdaMHsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y\n" 217 + "bmlhMRswGQYDVQQKDBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJv\n" 218 + "aWR3aWZpLmRldjEgMB4GA1UEAwwXU2VsZi1zaWduZWQgY2VydGlmaWNhdGUwggIi\n" 219 + "MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDD0oI2c+1D4D2wc4PnhkXbtA7g\n" 220 + "64Mp/JSbnVbl7PseJKnFD/pdos5joFXFbySFqu60S905T1a3AWNwbucKc7C7IwQw\n" 221 + "gtO7uMEPr35j7MhItyAbmj89dY729yXJ8gBnNnqc8PyYEIfZmnBvSry0Tsm60298\n" 222 + "GGZ9yCQfOOb4TJFX/CIKjniI170eLCiGybOrBvG11Rx6BwwHnk1cjkDspejrkhb0\n" 223 + "13RfkQ1S0cEnylrgnn/nRDAAnOscpHRerJ6Ud2vM64iIJy206ZyU/CrhcGeBWwi9\n" 224 + "C1F4ojzvgoFW7bJahXiyEaC5R3G5WdvX5qOr/eu/yMaCAner0LHUibHc5XA02F/c\n" 225 + "LO0LpN59tTT4dx9sLJVjZQGSUxyXnKHiR5TKkoAMWAZSO5hbE4drgivKLnYmYnhC\n" 226 + "Z1rGM5R0D0gB2llAvecItmynDJNApY6L1F8wnNA9NfGUYFpeqJ8uEOn7RxAvyYmB\n" 227 + "trmUFOqL7W84d1/XzORPGQ7n1wyPfBG3xyGIm2MMvanVsLs0/9NXAYAz2ZAHJPnS\n" 228 + "DsiV+7OHtMCdgTI5BJFmiJpXKgVE+IaewQdSjXDU7bgMlll3lTVoVAiKJmxpOmZ6\n" 229 + "FFz7mkd0pYhsO5jQpNGMfl+IaoIiTx4Zg9ZjwjTcPn9eGunBLJJ8SofkhM4boLrC\n" 230 + "KSen8NYuHVDPwAOwpQIDAQABo0MwQTAdBgNVHQ4EFgQU2IB1Q35ysx0HpRttAqMU\n" 231 + "FO9OhIAwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3\n" 232 + "DQEBDAUAA4ICAQBqf4zbooJ4hHeZs7Nd31G7i2WEr6/8OWTuEuDAmJkGW8WBeyUG\n" 233 + "JMrxF3U+kGxVGops4mSxMwVpcsqQa+IwkrP807dSqkuntLVGFqVo7rcQ+l8OcNUv\n" 234 + "oNQIFGPLlWPyMnjXvmWbfvgbgFoY9yUFoxFlHqsVf+1mEvTmW9ya4BGT2hlfvtb6\n" 235 + "Jfvrrocg9zGSnBs9oyI+GzP4Xdqd0riXfk6OuFH3R05/cQj7SlPm8LU1J7ZML/4H\n" 236 + "1AuMg+Ql8vxql4IzIk93CDR8Hq1jb3MhF/ae9UfttuNnHT4vu5X/6qLqWNKMs3zP\n" 237 + "DQQaYkqxWTUWiNlWV7i7pXn8e2J8ZkRHVELvrpdXLKIfL6RxjzKWY+TKiHY+F48I\n" 238 + "JwCAbL1FX+NzB2dS0RxXk/RTAxagenfmDcY1notHNsnDZB54cP9nv+N3wqkDoaKg\n" 239 + "nqOZTlIRWJ4agygqGaxieUuZRgy/AE/dSGpetlXAScKUvhCcO22qXL2jSjBAg5+k\n" 240 + "AynUuiZxdogXbvXrAwSWAVwlz8qEOK3NPFYnEKcjgNbTxiUHp3P/ULBgHQo55o9K\n" 241 + "DdUEbIurd02xG6usEDWxR5ds/RPy6VZ5c6bFUiTEsfMMmQotPL/btuPVXsSdJUR4\n" 242 + "xcxpcV7zx9IjFs/IylyQ1YEYDKWV+nH7iiOigO5WiZ5ck2Wa/Tk3uXg1Ew==\n" 243 + "-----END CERTIFICATE-----\n"; 244 245 private static final String TEST_FAKE_CA_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" 246 + "MIIGADCCA+igAwIBAgIUIxVGWM5Wrs86DpDA2+fo53UryqMwDQYJKoZIhvcNAQEM\n" 247 + "BQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQK\n" 248 + "DBJBbmRyb2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8\n" 249 + "MDoGA1UEAwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5k\n" 250 + "IGRldmVsb3BtZW50MB4XDTIzMDQxMzE1MzkyM1oXDTQzMDQwODE1MzkyM1owgZcx\n" 251 + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRswGQYDVQQKDBJBbmRy\n" 252 + "b2lkIFdpLUZpIFRlc3QxGDAWBgNVBAsMD2FuZHJvaWR3aWZpLm9lbTE8MDoGA1UE\n" 253 + "AwwzQW5kcm9pZCBQYXJ0bmVyIFJvb3QgQ0EgZm9yIHRlc3RpbmcgYW5kIGRldmVs\n" 254 + "b3BtZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAhTF8MJsucR5P\n" 255 + "6oN/Nho92EYz9b3m7n52m9KgI/G6/9bK9PSDZ6Z6U3qNxpG7nFML+5qyk+qeBHP8\n" 256 + "39lGNNoH1c2dQDXw3oLjOmd1UoN+zSZBznLwkDD8YQYafz1GWRcI34FYDgiPuSx7\n" 257 + "o4+O4hxcimrelhoNRQcRsrZFoUyJZjtPy2Z5DTZTB7udg1QwZ+7+pHCme3DB2Im/\n" 258 + "Eszsmm2TAG6yM3G/lxphLZMhUFy6kjeeIiuar56ED6dg7qEqdeIznt2gGKolXRWs\n" 259 + "vPW4a5NX1RUjsQxOcKEQnrXZXJ9mATptY1hOxuP6kg8Jzh0tN/NzyyERGFvnvhGz\n" 260 + "sN7CkTUhPOKUW3dVrKl9ZJ9PbYZ6xbpbOWOR/5znYQ/f3+bxxibbFI3WN/89VO50\n" 261 + "WEzwfmiGiWC6Bz0iBoAmGjCxySbJg8iDCjrbRexkFsOJ84jlY0fDrfaqY1+WuyYu\n" 262 + "vdk+w4lzk0wYRbp+oRuIXplMyZDsS15CPq+svoYeNCCOXlkRiMLuq/SpkdM8lRKp\n" 263 + "Mrsc1AckI+BGVqh8S9lyJoP67uDmba1FUw7X3IMCkZQwvFduLkJLNYwO6QDV2M6R\n" 264 + "nUCVCx+vxJdlIOLNQIAeKW9jzfASom4ehZY2HHErbUYGKzFQJJ/2+uQLLYn7PsaE\n" 265 + "gYTYA1naakQegCgbD2UsbKqrEfOiHEECAwEAAaNCMEAwHQYDVR0OBBYEFBiYeS/E\n" 266 + "IQ5+IoQ3bsXoibK3QuMzMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGG\n" 267 + "MA0GCSqGSIb3DQEBDAUAA4ICAQACOOZdfcQ53BF43glA/0VuFeXQ+VS+keR9aFBX\n" 268 + "caKrIbFXSns9EsnvKj1L/IoHem5k4LkMFoNgE1Skit2iktPYs6unV83p99PG6EQo\n" 269 + "RG1CeZ50cHzZK6N56MbwZUGRy/p6Zr9ak9d6XE8GpvSwMW8XebrLPtgSBvpI+WIZ\n" 270 + "epMVg7v8AIIRQuoR2VtZ7RZF/X1kwfU5t2aASVBnxTjlSy6KtBLuL+Vu4Aefa+Z0\n" 271 + "d9Ma2jZV+hwWp0X6piSrVKkMZIR5tlvwJootNBlO0J1Jn4J0ecGNEGXmFwz4adnK\n" 272 + "eYfpuNBJI4CKq7mv2Aszsvg0rQxfKlN8LV7gSNu3H6BjjkNUtHI6uwsajJfEmGKD\n" 273 + "YRpAFgZq7FzRwoI8uWr0Bucz6+qxpISi48t0pmceSVpn6UV1UdSebLo8CX5P283F\n" 274 + "yUqlw2hMpo22Gm3uW8GfPyHfMfsqfMU+7BCP38DDnhcGUO3CTINjREXUGtn6CuWS\n" 275 + "ImhmATld6KJNtRCql3zQnaEO84IvKdFVOkm5q9qQjNWDr1oYsLhxoZJZjKK2rP5F\n" 276 + "GRbMvqDhmzrV0yG+sIyW+aEjBl44bVjWQnFhGjtNr1BOOftSyjnseYiioLbiiaYG\n" 277 + "9Mqu78VmTWJzfxyOP2QPK5K00jnVBZ+jQH0NyIE9yf2Cg/llfYRoHsz80cfY/DNt\n" 278 + "jUR49A==\n" 279 + "-----END CERTIFICATE-----"; 280 281 @Mock WifiContext mContext; 282 @Mock WifiConfigManager mWifiConfigManager; 283 @Mock WifiNative mWifiNative; 284 @Mock FrameworkFacade mFrameworkFacade; 285 @Mock WifiNotificationManager mWifiNotificationManager; 286 @Mock WifiDialogManager mWifiDialogManager; 287 @Mock InsecureEapNetworkHandler.InsecureEapNetworkHandlerCallbacks mCallbacks; 288 @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Notification.Builder mNotificationBuilder; 289 @Mock private WifiDialogManager.DialogHandle mTofuAlertDialog; 290 @Mock private java.text.DateFormat mDateFormat; 291 @Mock private KeyStore mKeyStore; 292 293 @Captor ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor; 294 @Captor ArgumentCaptor<WifiConfigManager.OnNetworkUpdateListener> 295 mOnNetworkUpdateListenerCaptor; 296 297 TestLooper mLooper; 298 Handler mHandler; 299 MockResources mResources; 300 InsecureEapNetworkHandler mInsecureEapNetworkHandler; 301 302 private MockitoSession mSession; 303 304 /** 305 * Sets up for unit test 306 */ 307 @Before setUp()308 public void setUp() throws Exception { 309 MockitoAnnotations.initMocks(this); 310 mResources = new MockResources(); 311 when(mContext.getString(anyInt())).thenReturn("TestString"); 312 when(mContext.getString(anyInt(), any())).thenReturn("TestStringWithArgument"); 313 when(mContext.getText(anyInt())).thenReturn("TestStr"); 314 when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_issuer_name_text), 315 anyString())) 316 .thenAnswer((Answer<String>) invocation -> 317 "Issuer Name:\n" + invocation.getArguments()[1] + "\n\n"); 318 when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_server_name_text), 319 anyString())) 320 .thenAnswer((Answer<String>) invocation -> 321 "Server Name:\n" + invocation.getArguments()[1] + "\n\n"); 322 when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_organization_text), 323 anyString())) 324 .thenAnswer((Answer<String>) invocation -> 325 "Organization:\n" + invocation.getArguments()[1] + "\n\n"); 326 when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_contact_text), 327 anyString())) 328 .thenAnswer((Answer<String>) invocation -> 329 "Contact:\n" + invocation.getArguments()[1] + "\n\n"); 330 when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_signature_name_text), 331 anyString())) 332 .thenAnswer((Answer<String>) invocation -> 333 "SHA-256 Fingerprint:\n" + invocation.getArguments()[1] + "\n\n"); 334 when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources"); 335 when(mContext.getResources()).thenReturn(mResources); 336 when(mWifiDialogManager.createLegacySimpleDialogWithUrl( 337 any(), any(), any(), anyInt(), anyInt(), any(), any(), any(), any(), any())) 338 .thenReturn(mTofuAlertDialog); 339 when(mWifiDialogManager.createLegacySimpleDialog( 340 any(), any(), any(), any(), any(), any(), any())) 341 .thenReturn(mTofuAlertDialog); 342 343 when(mFrameworkFacade.makeNotificationBuilder(any(), any())) 344 .thenReturn(mNotificationBuilder); 345 346 // static mocking 347 mSession = ExtendedMockito.mockitoSession() 348 .mockStatic(DateFormat.class, withSettings().lenient()) 349 .mockStatic(KeyStore.class, withSettings().lenient()) 350 .startMocking(); 351 when(DateFormat.getMediumDateFormat(any())).thenReturn(mDateFormat); 352 when(mDateFormat.format(any())).thenReturn("April 12, 2023"); 353 when(KeyStore.getInstance(anyString())).thenReturn(mKeyStore); 354 355 mLooper = new TestLooper(); 356 mHandler = new Handler(mLooper.getLooper()); 357 } 358 359 @After cleanUp()360 public void cleanUp() throws Exception { 361 validateMockitoUsage(); 362 mSession.finishMocking(); 363 } 364 365 /** 366 * Verify Trust On First Use flow. 367 * - This network is selected by a user. 368 * - Accept the connection. 369 */ 370 @Test verifyTrustOnFirstUseAcceptWhenConnectByUser()371 public void verifyTrustOnFirstUseAcceptWhenConnectByUser() throws Exception { 372 assumeTrue(SdkLevel.isAtLeastT()); 373 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 374 boolean needUserApproval = true; 375 376 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 377 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 378 verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_ACCEPT, 379 isTrustOnFirstUseSupported, isUserSelected, needUserApproval); 380 } 381 382 /** 383 * Verify Trust On First Use flow. 384 * - This network is selected by a user. 385 * - Reject the connection. 386 */ 387 @Test verifyTrustOnFirstUseRejectWhenConnectByUser()388 public void verifyTrustOnFirstUseRejectWhenConnectByUser() throws Exception { 389 assumeTrue(SdkLevel.isAtLeastT()); 390 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 391 boolean needUserApproval = true; 392 393 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 394 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 395 verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_REJECT, 396 isTrustOnFirstUseSupported, isUserSelected, needUserApproval); 397 } 398 399 /** 400 * Verify Trust On First Use flow. 401 * - This network is auto-connected. 402 * - Accept the connection. 403 */ 404 @Test verifyTrustOnFirstUseAcceptWhenConnectByAutoConnect()405 public void verifyTrustOnFirstUseAcceptWhenConnectByAutoConnect() throws Exception { 406 assumeTrue(SdkLevel.isAtLeastT()); 407 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = false; 408 boolean needUserApproval = true; 409 410 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 411 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 412 verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_ACCEPT, 413 isTrustOnFirstUseSupported, isUserSelected, needUserApproval); 414 } 415 416 /** 417 * Verify Trust On First Use flow. 418 * - This network is auto-connected. 419 * - Reject the connection. 420 */ 421 @Test verifyTrustOnFirstUseRejectWhenConnectByAutoConnect()422 public void verifyTrustOnFirstUseRejectWhenConnectByAutoConnect() throws Exception { 423 assumeTrue(SdkLevel.isAtLeastT()); 424 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = false; 425 boolean needUserApproval = true; 426 427 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 428 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 429 verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_REJECT, 430 isTrustOnFirstUseSupported, isUserSelected, needUserApproval); 431 } 432 433 /** 434 * Verify Trust On First Use flow. 435 * - This network is auto-connected. 436 * - Tap the notification to show the dialog. 437 */ 438 @Test verifyTrustOnFirstUseTapWhenConnectByAutoConnect()439 public void verifyTrustOnFirstUseTapWhenConnectByAutoConnect() throws Exception { 440 assumeTrue(SdkLevel.isAtLeastT()); 441 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = false; 442 boolean needUserApproval = true; 443 444 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 445 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 446 verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_TAP, 447 isTrustOnFirstUseSupported, isUserSelected, needUserApproval); 448 } 449 450 /** 451 * Verify that it reports errors if there is no pending Root CA certifiate 452 * with Trust On First Use support. 453 */ 454 @Test verifyTrustOnFirstUseWhenTrustOnFirstUseNoPendingCert()455 public void verifyTrustOnFirstUseWhenTrustOnFirstUseNoPendingCert() throws Exception { 456 assumeTrue(SdkLevel.isAtLeastT()); 457 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 458 459 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 460 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 461 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 462 verify(mCallbacks).onError(eq(config.SSID)); 463 verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId), 464 eq(WifiConfiguration.NetworkSelectionStatus 465 .DISABLED_BY_WIFI_MANAGER)); 466 } 467 468 /** 469 * Verify that Trust On First Use is not supported on T. 470 * It follows the same behavior on preT release. 471 */ 472 @Test verifyTrustOnFirstUseWhenTrustOnFirstUseNotSupported()473 public void verifyTrustOnFirstUseWhenTrustOnFirstUseNotSupported() throws Exception { 474 assumeTrue(SdkLevel.isAtLeastT()); 475 boolean isAtLeastT = true, isTrustOnFirstUseSupported = false, isUserSelected = true; 476 477 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 478 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 479 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 480 verify(mCallbacks, never()).onError(any()); 481 } 482 483 /** 484 * Verify legacy insecure EAP network flow. 485 * - This network is selected by a user. 486 * - Accept the connection. 487 */ 488 @Test verifyLegacyEapNetworkAcceptWhenConnectByUser()489 public void verifyLegacyEapNetworkAcceptWhenConnectByUser() throws Exception { 490 assumeFalse(SdkLevel.isAtLeastT()); 491 boolean isAtLeastT = false, isTrustOnFirstUseSupported = false, isUserSelected = true; 492 boolean needUserApproval = true; 493 494 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 495 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 496 verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_ACCEPT, 497 isTrustOnFirstUseSupported, isUserSelected, needUserApproval); 498 } 499 500 /** 501 * Verify legacy insecure EAP network flow. 502 * - Trust On First Use is not supported. 503 * - This network is selected by a user. 504 * - Reject the connection. 505 */ 506 @Test verifyLegacyEapNetworkRejectWhenConnectByUser()507 public void verifyLegacyEapNetworkRejectWhenConnectByUser() throws Exception { 508 assumeFalse(SdkLevel.isAtLeastT()); 509 boolean isAtLeastT = false, isTrustOnFirstUseSupported = false, isUserSelected = true; 510 boolean needUserApproval = true; 511 512 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 513 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 514 verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_REJECT, 515 isTrustOnFirstUseSupported, isUserSelected, needUserApproval); 516 } 517 518 /** 519 * Verify legacy insecure EAP network flow. 520 * - This network is auto-connected. 521 * - Accept the connection. 522 */ 523 @Test verifyLegacyEapNetworkAcceptWhenAutoConnect()524 public void verifyLegacyEapNetworkAcceptWhenAutoConnect() throws Exception { 525 assumeFalse(SdkLevel.isAtLeastT()); 526 boolean isAtLeastT = false, isTrustOnFirstUseSupported = false, isUserSelected = false; 527 boolean needUserApproval = true; 528 529 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 530 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 531 verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_ACCEPT, 532 isTrustOnFirstUseSupported, isUserSelected, needUserApproval); 533 } 534 535 /** 536 * Verify legacy insecure EAP network flow. 537 * - Trust On First Use is not supported. 538 * - This network is auto-connected. 539 * - Reject the connection. 540 */ 541 @Test verifyLegacyEapNetworkRejectWhenAutoConnect()542 public void verifyLegacyEapNetworkRejectWhenAutoConnect() throws Exception { 543 assumeFalse(SdkLevel.isAtLeastT()); 544 boolean isAtLeastT = false, isTrustOnFirstUseSupported = false, isUserSelected = false; 545 boolean needUserApproval = true; 546 547 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 548 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 549 verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_REJECT, 550 isTrustOnFirstUseSupported, isUserSelected, needUserApproval); 551 } 552 553 /** 554 * Verify legacy insecure EAP network flow. 555 * - This network is selected by a user. 556 * - Tap the notification 557 */ 558 @Test verifyLegacyEapNetworkOpenLinkWhenConnectByUser()559 public void verifyLegacyEapNetworkOpenLinkWhenConnectByUser() throws Exception { 560 assumeFalse(SdkLevel.isAtLeastT()); 561 boolean isAtLeastT = false, isTrustOnFirstUseSupported = false, isUserSelected = true; 562 boolean needUserApproval = true; 563 564 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 565 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 566 verifyTrustOnFirstUseFlowWithDefaultCerts(config, ACTION_TAP, 567 isTrustOnFirstUseSupported, isUserSelected, needUserApproval); 568 } 569 570 /** 571 * Verify Trust On First Use flow with server certificate pinning 572 * - Single depth server certificate by signed by some unknown issuer, CA flag not set 573 * - This network is selected by a user. 574 * - Accept the connection. 575 */ 576 @Test verifyTrustOnFirstUseFlowWithServerCertPinning1()577 public void verifyTrustOnFirstUseFlowWithServerCertPinning1() throws Exception { 578 assumeTrue(SdkLevel.isAtLeastT()); 579 runServerCertPinningTest(TEST_GEN_SERVER_CERT); 580 } 581 582 /** 583 * Verify Trust On First Use flow with server certificate pinning 584 * - Single depth server certificate by signed by some unknown issuer, CA flag set 585 * - This network is selected by a user. 586 * - Accept the connection. 587 */ 588 @Test verifyTrustOnFirstUseFlowWithServerCertPinning2()589 public void verifyTrustOnFirstUseFlowWithServerCertPinning2() throws Exception { 590 assumeTrue(SdkLevel.isAtLeastT()); 591 runServerCertPinningTest(TEST_GEN_CA_CERT); 592 } 593 runServerCertPinningTest(int type)594 private void runServerCertPinningTest(int type) 595 throws Exception { 596 WifiConfiguration config = prepareWifiConfiguration(true); 597 setupTest(config, true, true); 598 599 CertificateEventInfo mockServerCert = generateMockCertEventInfo(type); 600 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockServerCert); 601 verifyTrustOnFirstUseFlow(config, ACTION_ACCEPT, true, 602 true, false, null, mockServerCert.getCert(), 603 null); 604 } 605 606 /** 607 * Verify Trust On First Use flow with the CA certificate path. 608 * - Single depth server certificate by signed by a trusted Root CA from the trust store. 609 * - This network is selected by a user. 610 * - Accept the connection. 611 */ 612 @Test verifyTrustOnFirstUseFlowWithRootCaFromFromStore()613 public void verifyTrustOnFirstUseFlowWithRootCaFromFromStore() throws Exception { 614 assumeTrue(SdkLevel.isAtLeastU()); 615 runServerCertFromTrustStoreTest(); 616 } 617 runServerCertFromTrustStoreTest()618 private void runServerCertFromTrustStoreTest() throws Exception { 619 WifiConfiguration config = configureTofuWithAidlVersion2Value(true); 620 621 // CA_CERT is also in the trust store 622 CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_CA_CERT); 623 CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT); 624 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1, mockCaCert); 625 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockServerCert); 626 627 List<String> aliases = new ArrayList<>(); 628 aliases.add("TEST_GEN_CA_CERT"); 629 aliases.add("TEST_GEN_CA2_CERT"); 630 when(mKeyStore.aliases()).thenReturn(Collections.enumeration(aliases)); 631 when(mKeyStore.getCertificate("TEST_GEN_CA_CERT")) 632 .thenReturn(getCertificate(TEST_GEN_CA_CERT)); 633 when(mKeyStore.getCertificate("TEST_GEN_CA2_CERT")) 634 .thenReturn(getCertificate(TEST_GEN_CA2_CERT)); 635 verifyTrustOnFirstUseFlow(config, ACTION_ACCEPT, true, 636 true, false, mockCaCert.getCert(), mockServerCert.getCert(), 637 WifiConfigurationUtil.getSystemTrustStorePath()); 638 } 639 generateMockCertEventInfo(int type)640 private CertificateEventInfo generateMockCertEventInfo(int type) throws Exception { 641 CertificateEventInfo certificateEventInfo = mock(CertificateEventInfo.class); 642 X509Certificate cert = getCertificate(type); 643 644 when(certificateEventInfo.getCert()).thenReturn(cert); 645 when(certificateEventInfo.getCertHash()).thenReturn("12345678"); 646 return certificateEventInfo; 647 } 648 getCertificate(int type)649 private X509Certificate getCertificate(int type) throws Exception { 650 String certString; 651 652 if (type == TEST_GEN_CA_CERT) { 653 certString = TEST_CA_CERTIFICATE; 654 } else if (type == TEST_GEN_CA2_CERT) { 655 certString = TEST_CA2_CERTIFICATE; 656 } else if (type == TEST_GEN_SERVER_CERT) { 657 certString = TEST_SERVER_CERTIFICATE; 658 } else if (type == TEST_GEN_SELF_SIGNED_CERT) { 659 certString = TEST_SELF_SIGNED_CERTIFICATE; 660 } else if (type == TEST_GEN_FAKE_CA_CERT) { 661 certString = TEST_FAKE_CA_CERTIFICATE; 662 } else { 663 throw (new Exception()); 664 } 665 666 CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 667 InputStream in = new ByteArrayInputStream(certString.getBytes()); 668 return (X509Certificate) certFactory.generateCertificate(in); 669 } 670 prepareWifiConfiguration(boolean isAtLeastT)671 private WifiConfiguration prepareWifiConfiguration(boolean isAtLeastT) { 672 WifiConfiguration config = spy(WifiConfigurationTestUtil.createEapNetwork( 673 WifiEnterpriseConfig.Eap.TTLS, WifiEnterpriseConfig.Phase2.MSCHAPV2)); 674 config.networkId = FRAMEWORK_NETWORK_ID; 675 config.SSID = TEST_SSID; 676 if (isAtLeastT) { 677 config.enterpriseConfig.enableTrustOnFirstUse(true); 678 } 679 config.enterpriseConfig.setCaPath(""); 680 config.enterpriseConfig.setDomainSuffixMatch(""); 681 config.enterpriseConfig.setIdentity(TEST_IDENTITY); 682 config.enterpriseConfig.setPassword(TEST_PASSWORD); 683 return config; 684 } 685 setupTest(WifiConfiguration config, boolean isAtLeastT, boolean isTrustOnFirstUseSupported)686 private void setupTest(WifiConfiguration config, 687 boolean isAtLeastT, boolean isTrustOnFirstUseSupported) { 688 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported, false); 689 } 690 setupTest(WifiConfiguration config, boolean isAtLeastT, boolean isTrustOnFirstUseSupported, boolean isInsecureEnterpriseConfigurationAllowed)691 private void setupTest(WifiConfiguration config, 692 boolean isAtLeastT, boolean isTrustOnFirstUseSupported, 693 boolean isInsecureEnterpriseConfigurationAllowed) { 694 mInsecureEapNetworkHandler = new InsecureEapNetworkHandler( 695 mContext, 696 mWifiConfigManager, 697 mWifiNative, 698 mFrameworkFacade, 699 mWifiNotificationManager, 700 mWifiDialogManager, 701 isTrustOnFirstUseSupported, 702 isInsecureEnterpriseConfigurationAllowed, 703 mCallbacks, 704 WIFI_IFACE_NAME, 705 mHandler); 706 707 if (isTrustOnFirstUseSupported 708 && (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS 709 || config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP) 710 && config.enterpriseConfig.getPhase2Method() != WifiEnterpriseConfig.Phase2.NONE) { 711 // Verify that the configuration contains an identity 712 assertEquals(TEST_IDENTITY, config.enterpriseConfig.getIdentity()); 713 assertTrue(TextUtils.isEmpty(config.enterpriseConfig.getAnonymousIdentity())); 714 assertEquals(TEST_PASSWORD, config.enterpriseConfig.getPassword()); 715 } 716 mInsecureEapNetworkHandler.prepareConnection(config); 717 718 if (isTrustOnFirstUseSupported && config.enterpriseConfig.isTrustOnFirstUseEnabled() 719 && (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS 720 || config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP) 721 && config.enterpriseConfig.getPhase2Method() != WifiEnterpriseConfig.Phase2.NONE) { 722 // Verify identities are cleared 723 assertTrue(TextUtils.isEmpty(config.enterpriseConfig.getIdentity())); 724 assertEquals(TOFU_ANONYMOUS_IDENTITY, config.enterpriseConfig.getAnonymousIdentity()); 725 assertTrue(TextUtils.isEmpty(config.enterpriseConfig.getPassword())); 726 } 727 728 if (isTrustOnFirstUseSupported && config.enterpriseConfig.isTrustOnFirstUseEnabled()) { 729 verify(mContext, atLeastOnce()).registerReceiver( 730 mBroadcastReceiverCaptor.capture(), 731 argThat(f -> f.hasAction(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_TAP)), 732 eq(null), 733 eq(mHandler)); 734 } else if ((isTrustOnFirstUseSupported 735 && !config.enterpriseConfig.isTrustOnFirstUseEnabled() 736 && isInsecureEnterpriseConfigurationAllowed) 737 || !isTrustOnFirstUseSupported) { 738 verify(mContext, atLeastOnce()).registerReceiver( 739 mBroadcastReceiverCaptor.capture(), 740 argThat(f -> f.hasAction(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_ACCEPT) 741 && f.hasAction(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_REJECT)), 742 eq(null), 743 eq(mHandler)); 744 } 745 746 verify(mWifiConfigManager).addOnNetworkUpdateListener( 747 mOnNetworkUpdateListenerCaptor.capture()); 748 } 749 750 /** 751 * Verify Trust On First Use flow with a minimal cert chain 752 * - This network is selected by a user. 753 * - Accept the connection. 754 */ 755 @Test verifyTrustOnFirstUseAcceptWhenConnectByUserWithMinimalChain()756 public void verifyTrustOnFirstUseAcceptWhenConnectByUserWithMinimalChain() throws Exception { 757 assumeTrue(SdkLevel.isAtLeastT()); 758 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 759 boolean needUserApproval = true; 760 761 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 762 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 763 764 CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_CA_CERT); 765 CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT); 766 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1, mockCaCert); 767 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockServerCert); 768 769 verifyTrustOnFirstUseFlow(config, ACTION_ACCEPT, isTrustOnFirstUseSupported, 770 isUserSelected, needUserApproval, mockCaCert.getCert(), mockServerCert.getCert(), 771 null); 772 } 773 774 /** 775 * Verify Trust On First Use flow with a self-signed CA cert. 776 * - This network is selected by a user. 777 * - Forget the connection. 778 */ 779 @Test verifyTrustOnFirstUseForgetWhenConnectByUserWithSelfSignedCaCert()780 public void verifyTrustOnFirstUseForgetWhenConnectByUserWithSelfSignedCaCert() 781 throws Exception { 782 assumeTrue(SdkLevel.isAtLeastT()); 783 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 784 boolean needUserApproval = true; 785 786 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 787 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 788 789 CertificateEventInfo mockSelfSignedCert = 790 generateMockCertEventInfo(TEST_GEN_SELF_SIGNED_CERT); 791 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockSelfSignedCert); 792 793 verifyTrustOnFirstUseFlow(config, ACTION_FORGET, isTrustOnFirstUseSupported, 794 isUserSelected, needUserApproval, mockSelfSignedCert.getCert(), 795 mockSelfSignedCert.getCert(), null); 796 } 797 798 /** 799 * Verify that the connection should be terminated. 800 * - TOFU is supported. 801 * - Insecure EAP network is not allowed. 802 * - No cert is received. 803 */ 804 @Test verifyOnErrorWithoutCert()805 public void verifyOnErrorWithoutCert() throws Exception { 806 assumeTrue(SdkLevel.isAtLeastT()); 807 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 808 809 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 810 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 811 812 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 813 verify(mCallbacks).onError(eq(config.SSID)); 814 verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId), 815 eq(WifiConfiguration.NetworkSelectionStatus 816 .DISABLED_BY_WIFI_MANAGER)); 817 } 818 819 /** 820 * Verify that the connection should be upgraded to TOFU. 821 * - TOFU is supported. 822 * - Insecure EAP network is not allowed. 823 * - TOFU is not enabled 824 */ 825 @Test verifyOnErrorWithTofuDisabledWhenInsecureEapNetworkIsNotAllowed()826 public void verifyOnErrorWithTofuDisabledWhenInsecureEapNetworkIsNotAllowed() 827 throws Exception { 828 assumeTrue(SdkLevel.isAtLeastT()); 829 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 830 831 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 832 config.enterpriseConfig.enableTrustOnFirstUse(false); 833 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 834 835 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1, 836 generateMockCertEventInfo(TEST_GEN_CA_CERT)); 837 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, 838 generateMockCertEventInfo(TEST_GEN_SERVER_CERT)); 839 840 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 841 assertTrue(config.enterpriseConfig.isTrustOnFirstUseEnabled()); 842 } 843 844 /** 845 * Verify that no error occurs in insecure network handling flow. 846 * - TOFU is supported. 847 * - Insecure EAP network is allowed. 848 * - TOFU is not enabled 849 * - No user approval is needed. 850 */ 851 @Test verifyNoErrorWithTofuDisabledWhenInsecureEapNetworkIsAllowed()852 public void verifyNoErrorWithTofuDisabledWhenInsecureEapNetworkIsAllowed() 853 throws Exception { 854 assumeTrue(SdkLevel.isAtLeastT()); 855 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 856 boolean isInsecureEnterpriseConfigurationAllowed = true; 857 858 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 859 config.enterpriseConfig.enableTrustOnFirstUse(false); 860 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported, 861 isInsecureEnterpriseConfigurationAllowed); 862 863 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1, 864 generateMockCertEventInfo(TEST_GEN_CA_CERT)); 865 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, 866 generateMockCertEventInfo(TEST_GEN_SERVER_CERT)); 867 868 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 869 verify(mCallbacks, never()).onError(any()); 870 } 871 872 /** 873 * Verify that is reports errors if the server cert issuer does not match the parent subject. 874 */ 875 @Test verifyOnErrorWithIncompleteChain()876 public void verifyOnErrorWithIncompleteChain() throws Exception { 877 assumeTrue(SdkLevel.isAtLeastT()); 878 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 879 880 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 881 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 882 883 CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_CA2_CERT); 884 // Missing intermediate cert. 885 CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT); 886 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1, mockCaCert); 887 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockServerCert); 888 889 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 890 verify(mCallbacks).onError(eq(config.SSID)); 891 verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId), 892 eq(WifiConfiguration.NetworkSelectionStatus 893 .DISABLED_BY_WIFI_MANAGER)); 894 } 895 896 /** 897 * Verify that it reports errors if the issuer is a fake Root CA with the same subject of the 898 * real Root CA. Simulates an attack where the leaf is copied from the real server but a fake 899 * Root CA that an attacker controls is attached. 900 */ 901 @Test verifyOnErrorWithFakeRootCaCertInTheChain()902 public void verifyOnErrorWithFakeRootCaCertInTheChain() throws Exception { 903 assumeTrue(SdkLevel.isAtLeastT()); 904 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 905 906 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 907 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 908 909 // Fake Root CA that didn't sign the server cert 910 CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_FAKE_CA_CERT); 911 CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT); 912 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1, mockCaCert); 913 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockServerCert); 914 915 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 916 verify(mCallbacks).onError(eq(config.SSID)); 917 verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId), 918 eq(WifiConfiguration.NetworkSelectionStatus 919 .DISABLED_BY_WIFI_MANAGER)); 920 } 921 922 /** 923 * Verify that setting pending certificate won't crash with no current configuration. 924 */ 925 @Test verifySetPendingCertificateNoCrashWithNoConfig()926 public void verifySetPendingCertificateNoCrashWithNoConfig() 927 throws Exception { 928 assumeTrue(SdkLevel.isAtLeastT()); 929 mInsecureEapNetworkHandler = new InsecureEapNetworkHandler( 930 mContext, 931 mWifiConfigManager, 932 mWifiNative, 933 mFrameworkFacade, 934 mWifiNotificationManager, 935 mWifiDialogManager, 936 true /* isTrustOnFirstUseSupported */, 937 false /* isInsecureEnterpriseConfigurationAllowed */, 938 mCallbacks, 939 WIFI_IFACE_NAME, 940 mHandler); 941 CertificateEventInfo mockSelfSignedCert = 942 generateMockCertEventInfo(TEST_GEN_SELF_SIGNED_CERT); 943 mInsecureEapNetworkHandler.addPendingCertificate("NotExist", 0, mockSelfSignedCert); 944 } 945 946 @Test testExistingCertChainIsClearedOnPreparingNewConnection()947 public void testExistingCertChainIsClearedOnPreparingNewConnection() throws Exception { 948 assumeTrue(SdkLevel.isAtLeastT()); 949 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 950 951 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 952 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 953 954 // Missing root CA cert. 955 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, 956 generateMockCertEventInfo(TEST_GEN_SERVER_CERT)); 957 958 // The wrong cert chain should be cleared after this call. 959 mInsecureEapNetworkHandler.prepareConnection(config); 960 961 CertificateEventInfo mockSelfSignedCert = 962 generateMockCertEventInfo(TEST_GEN_SELF_SIGNED_CERT); 963 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockSelfSignedCert); 964 965 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 966 verify(mCallbacks, never()).onError(any()); 967 } 968 969 @Test verifyUserApprovalIsNotNeededWithDifferentTargetConfig()970 public void verifyUserApprovalIsNotNeededWithDifferentTargetConfig() throws Exception { 971 assumeTrue(SdkLevel.isAtLeastT()); 972 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true; 973 974 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 975 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 976 977 CertificateEventInfo mockSelfSignedCert = 978 generateMockCertEventInfo(TEST_GEN_SELF_SIGNED_CERT); 979 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockSelfSignedCert); 980 981 // Pass another PSK config which is not the same as the current one. 982 WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork(); 983 pskConfig.networkId = FRAMEWORK_NETWORK_ID + 2; 984 mInsecureEapNetworkHandler.prepareConnection(pskConfig); 985 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 986 verify(mCallbacks, never()).onError(any()); 987 988 // Pass another non-TOFU EAP config which is not the same as the current one. 989 WifiConfiguration anotherEapConfig = spy(WifiConfigurationTestUtil.createEapNetwork( 990 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE)); 991 anotherEapConfig.networkId = FRAMEWORK_NETWORK_ID + 1; 992 mInsecureEapNetworkHandler.prepareConnection(anotherEapConfig); 993 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 994 verify(mCallbacks, never()).onError(any()); 995 } 996 verifyTrustOnFirstUseFlowWithDefaultCerts(WifiConfiguration config, int action, boolean isTrustOnFirstUseSupported, boolean isUserSelected, boolean needUserApproval)997 private void verifyTrustOnFirstUseFlowWithDefaultCerts(WifiConfiguration config, 998 int action, boolean isTrustOnFirstUseSupported, boolean isUserSelected, 999 boolean needUserApproval) throws Exception { 1000 CertificateEventInfo mockCaCert = generateMockCertEventInfo(TEST_GEN_CA_CERT); 1001 CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT); 1002 if (isTrustOnFirstUseSupported) { 1003 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1, mockCaCert); 1004 mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockServerCert); 1005 } 1006 verifyTrustOnFirstUseFlow(config, action, isTrustOnFirstUseSupported, 1007 isUserSelected, needUserApproval, mockCaCert.getCert(), mockServerCert.getCert(), 1008 null); 1009 } 1010 verifyTrustOnFirstUseFlow(WifiConfiguration config, int action, boolean isTrustOnFirstUseSupported, boolean isUserSelected, boolean needUserApproval, X509Certificate expectedCaCert, X509Certificate expectedServerCert, String expectedCaPath)1011 private void verifyTrustOnFirstUseFlow(WifiConfiguration config, 1012 int action, boolean isTrustOnFirstUseSupported, boolean isUserSelected, 1013 boolean needUserApproval, X509Certificate expectedCaCert, 1014 X509Certificate expectedServerCert, String expectedCaPath) throws Exception { 1015 mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected); 1016 1017 ArgumentCaptor<String> dialogMessageCaptor = ArgumentCaptor.forClass(String.class); 1018 if (isUserSelected) { 1019 ArgumentCaptor<WifiDialogManager.SimpleDialogCallback> dialogCallbackCaptor = 1020 ArgumentCaptor.forClass(WifiDialogManager.SimpleDialogCallback.class); 1021 verify(mWifiDialogManager).createLegacySimpleDialogWithUrl( 1022 any(), dialogMessageCaptor.capture(), any(), anyInt(), anyInt(), any(), any(), 1023 any(), dialogCallbackCaptor.capture(), any()); 1024 if (isTrustOnFirstUseSupported) { 1025 assertTofuDialogMessage(expectedServerCert, 1026 dialogMessageCaptor.getValue()); 1027 } 1028 if (action == ACTION_ACCEPT) { 1029 dialogCallbackCaptor.getValue().onPositiveButtonClicked(); 1030 } else if (action == ACTION_REJECT) { 1031 dialogCallbackCaptor.getValue().onNegativeButtonClicked(); 1032 } else if (action == ACTION_FORGET) { 1033 mOnNetworkUpdateListenerCaptor.getValue().onNetworkRemoved(config); 1034 } 1035 } else { 1036 verify(mFrameworkFacade, never()).makeAlertDialogBuilder(any()); 1037 verify(mFrameworkFacade).makeNotificationBuilder( 1038 eq(mContext), eq(WifiService.NOTIFICATION_NETWORK_ALERTS)); 1039 1040 // Trust On First Use notification has no accept and reject action buttons. 1041 // It only supports TAP and launch the dialog. 1042 if (isTrustOnFirstUseSupported) { 1043 Intent intent = new Intent(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_TAP); 1044 intent.putExtra(InsecureEapNetworkHandler.EXTRA_PENDING_CERT_SSID, TEST_SSID); 1045 BroadcastReceiver br = mBroadcastReceiverCaptor.getValue(); 1046 br.onReceive(mContext, intent); 1047 ArgumentCaptor<WifiDialogManager.SimpleDialogCallback> dialogCallbackCaptor = 1048 ArgumentCaptor.forClass(WifiDialogManager.SimpleDialogCallback.class); 1049 verify(mWifiDialogManager).createLegacySimpleDialogWithUrl( 1050 any(), dialogMessageCaptor.capture(), any(), anyInt(), anyInt(), any(), 1051 any(), any(), dialogCallbackCaptor.capture(), any()); 1052 assertTofuDialogMessage(expectedServerCert, 1053 dialogMessageCaptor.getValue()); 1054 if (action == ACTION_ACCEPT) { 1055 dialogCallbackCaptor.getValue().onPositiveButtonClicked(); 1056 } else if (action == ACTION_REJECT) { 1057 dialogCallbackCaptor.getValue().onNegativeButtonClicked(); 1058 } 1059 } else { 1060 Intent intent = new Intent(); 1061 if (action == ACTION_ACCEPT) { 1062 intent = new Intent(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_ACCEPT); 1063 } else if (action == ACTION_REJECT) { 1064 intent = new Intent(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_REJECT); 1065 } else if (action == ACTION_TAP) { 1066 intent = new Intent(InsecureEapNetworkHandler.ACTION_CERT_NOTIF_TAP); 1067 } 1068 intent.putExtra(InsecureEapNetworkHandler.EXTRA_PENDING_CERT_SSID, TEST_SSID); 1069 BroadcastReceiver br = mBroadcastReceiverCaptor.getValue(); 1070 br.onReceive(mContext, intent); 1071 } 1072 } 1073 1074 if (action == ACTION_ACCEPT) { 1075 verify(mWifiConfigManager).updateNetworkSelectionStatus(eq(config.networkId), 1076 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE)); 1077 if (isTrustOnFirstUseSupported) { 1078 if (!TextUtils.isEmpty(expectedCaPath)) { 1079 // Simulate Root CA from trust store 1080 verify(mWifiConfigManager).updateCaCertificate( 1081 eq(config.networkId), eq(expectedCaCert), eq(expectedServerCert), 1082 eq(null), eq(true)); 1083 } else if (expectedCaCert == null) { 1084 // Simulate server cert pinning case where there is no Root CA 1085 verify(mWifiConfigManager).updateCaCertificate( 1086 eq(config.networkId), eq(expectedServerCert), eq(expectedServerCert), 1087 eq("12345678"), eq(false)); // Server certificate hash 1088 } else { 1089 verify(mWifiConfigManager).updateCaCertificate( 1090 eq(config.networkId), eq(expectedCaCert), eq(expectedServerCert), 1091 eq(null), eq(false)); // Cert pinning not used 1092 } 1093 } else { 1094 verify(mWifiConfigManager, never()).updateCaCertificate( 1095 anyInt(), any(), any(), any(), anyBoolean()); 1096 } 1097 verify(mCallbacks).onAccept(eq(config.SSID), eq(config.networkId)); 1098 } else if (action == ACTION_REJECT) { 1099 verify(mWifiConfigManager, atLeastOnce()) 1100 .updateNetworkSelectionStatus(eq(config.networkId), 1101 eq(WifiConfiguration.NetworkSelectionStatus 1102 .DISABLED_BY_WIFI_MANAGER)); 1103 verify(mCallbacks).onReject(eq(config.SSID), eq(!isTrustOnFirstUseSupported)); 1104 } else if (action == ACTION_TAP) { 1105 verify(mWifiDialogManager).createLegacySimpleDialogWithUrl( 1106 any(), any(), any(), anyInt(), anyInt(), any(), any(), any(), any(), any()); 1107 verify(mTofuAlertDialog).launchDialog(); 1108 } else if (action == ACTION_FORGET) { 1109 verify(mTofuAlertDialog).dismissDialog(); 1110 } 1111 verify(mCallbacks, never()).onError(any()); 1112 } 1113 assertTofuDialogMessage( X509Certificate serverCert, String message)1114 private void assertTofuDialogMessage( 1115 X509Certificate serverCert, 1116 String message) { 1117 CertificateSubjectInfo serverCertSubjectInfo = 1118 CertificateSubjectInfo.parse(serverCert.getSubjectX500Principal().getName()); 1119 CertificateSubjectInfo serverCertIssuerInfo = 1120 CertificateSubjectInfo.parse(serverCert.getIssuerX500Principal().getName()); 1121 assertNotNull("Server cert subject info is null", serverCertSubjectInfo); 1122 assertNotNull("Server cert issuer info is null", serverCertIssuerInfo); 1123 1124 assertTrue("TOFU dialog message does not contain server cert subject name ", 1125 message.contains(serverCertSubjectInfo.commonName)); 1126 assertTrue("TOFU dialog message does not contain server cert issuer name", 1127 message.contains(serverCertIssuerInfo.commonName)); 1128 if (!TextUtils.isEmpty(serverCertSubjectInfo.organization)) { 1129 assertTrue("TOFU dialog message does not contain server cert organization", 1130 message.contains(serverCertSubjectInfo.organization)); 1131 } 1132 } 1133 1134 @Test testCleanUp()1135 public void testCleanUp() throws Exception { 1136 assumeTrue(SdkLevel.isAtLeastT()); 1137 1138 boolean isAtLeastT = true, isTrustOnFirstUseSupported = true; 1139 WifiConfiguration config = prepareWifiConfiguration(isAtLeastT); 1140 setupTest(config, isAtLeastT, isTrustOnFirstUseSupported); 1141 1142 BroadcastReceiver br = mBroadcastReceiverCaptor.getValue(); 1143 mInsecureEapNetworkHandler.cleanup(); 1144 verify(mContext).unregisterReceiver(br); 1145 verify(mWifiConfigManager).removeOnNetworkUpdateListener( 1146 mOnNetworkUpdateListenerCaptor.capture()); 1147 } 1148 1149 /** 1150 * Verify the getDigest and fingerprint methods 1151 */ 1152 @Test verifyGetDigest()1153 public void verifyGetDigest() throws Exception { 1154 CertificateEventInfo mockServerCert = generateMockCertEventInfo(TEST_GEN_SERVER_CERT); 1155 assertEquals(TEST_EXPECTED_SHA_256_SIGNATURE, 1156 mInsecureEapNetworkHandler.getDigest(mockServerCert.getCert(), "SHA256")); 1157 } 1158 1159 @Test verifyTrustStoreUsedForAidlVersion2AndUp()1160 public void verifyTrustStoreUsedForAidlVersion2AndUp() throws Exception { 1161 WifiConfiguration config = configureTofuWithAidlVersion2Value(true); 1162 verify(config.enterpriseConfig) 1163 .setCaPath(eq(WifiConfigurationUtil.getSystemTrustStorePath())); 1164 } 1165 1166 @Test verifyTrustStoreUsedForAidlVersionBelow2()1167 public void verifyTrustStoreUsedForAidlVersionBelow2() throws Exception { 1168 WifiConfiguration config = configureTofuWithAidlVersion2Value(false); 1169 verify(config.enterpriseConfig, never()).setCaPath(anyString()); 1170 } 1171 configureTofuWithAidlVersion2Value(boolean aidlVersion2OrUp)1172 private WifiConfiguration configureTofuWithAidlVersion2Value(boolean aidlVersion2OrUp) { 1173 mInsecureEapNetworkHandler = new InsecureEapNetworkHandler( 1174 mContext, 1175 mWifiConfigManager, 1176 mWifiNative, 1177 mFrameworkFacade, 1178 mWifiNotificationManager, 1179 mWifiDialogManager, 1180 true, 1181 false, 1182 mCallbacks, 1183 WIFI_IFACE_NAME, 1184 mHandler); 1185 1186 when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(anyInt())) 1187 .thenReturn(aidlVersion2OrUp); 1188 1189 WifiConfiguration config = spy(WifiConfigurationTestUtil.createEapNetwork( 1190 WifiEnterpriseConfig.Eap.TTLS, WifiEnterpriseConfig.Phase2.MSCHAPV2)); 1191 config.networkId = FRAMEWORK_NETWORK_ID; 1192 config.SSID = TEST_SSID; 1193 WifiEnterpriseConfig enterpriseConfig = mock(WifiEnterpriseConfig.class); 1194 when(enterpriseConfig.isTrustOnFirstUseEnabled()).thenReturn(true); 1195 when(enterpriseConfig.isEapMethodServerCertUsed()).thenReturn(true); 1196 when(enterpriseConfig.hasCaCertificate()).thenReturn(false); 1197 when(enterpriseConfig.isUserApproveNoCaCert()).thenReturn(false); 1198 config.enterpriseConfig = enterpriseConfig; 1199 1200 mInsecureEapNetworkHandler.prepareConnection(config); 1201 return config; 1202 } 1203 } 1204