summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-02-04 03:48:46 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-02-04 03:48:46 +0000
commitd61d9490e1bc9535a2d98b8d0f7d991157cb5dfd (patch)
tree697c2f8aae4c8a096b3edc089080e2f37979d709
parentbe17dd7542946fbeaf015c2285f2753a18a223a4 (diff)
parent6945ee7cf57b2d6eb24d65be5be456975653672f (diff)
downloadWifi-android13-qpr2-s5-release.tar.gz
Change-Id: I075575a959222734a1774e78ae929e35bad40186
-rw-r--r--service/ServiceWifiResources/res/values/overlayable.xml24
-rw-r--r--service/ServiceWifiResources/res/values/strings.xml3
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java56
-rw-r--r--service/java/com/android/server/wifi/InsecureEapNetworkHandler.java394
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java7
-rw-r--r--service/proto/src/metrics.proto3
-rw-r--r--service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java136
-rw-r--r--service/tests/wifitests/src/com/android/server/wifi/InsecureEapNetworkHandlerTest.java342
8 files changed, 220 insertions, 745 deletions
diff --git a/service/ServiceWifiResources/res/values/overlayable.xml b/service/ServiceWifiResources/res/values/overlayable.xml
index 75c90a3887..2eef3f5156 100644
--- a/service/ServiceWifiResources/res/values/overlayable.xml
+++ b/service/ServiceWifiResources/res/values/overlayable.xml
@@ -321,30 +321,6 @@
<item type="string" name="wifi_interface_priority_message_plural" />
<item type="string" name="wifi_interface_priority_approve" />
<item type="string" name="wifi_interface_priority_reject" />
- <item type="string" name="wifi_ca_cert_dialog_title" />
- <item type="string" name="wifi_ca_cert_dialog_continue_text" />
- <item type="string" name="wifi_ca_cert_dialog_abort_text" />
- <item type="string" name="wifi_ca_cert_dialog_message_hint" />
- <item type="string" name="wifi_ca_cert_dialog_message_server_name_text" />
- <item type="string" name="wifi_ca_cert_dialog_message_issuer_name_text" />
- <item type="string" name="wifi_ca_cert_dialog_message_organization_text" />
- <item type="string" name="wifi_ca_cert_dialog_message_contact_text" />
- <item type="string" name="wifi_ca_cert_dialog_message_signature_name_text" />
- <item type="string" name="wifi_ca_cert_notification_title" />
- <item type="string" name="wifi_ca_cert_notification_message" />
- <item type="string" name="wifi_ca_cert_failed_to_install_ca_cert" />
- <item type="string" name="wifi_ca_cert_dialog_preT_title" />
- <item type="string" name="wifi_ca_cert_dialog_preT_continue_text" />
- <item type="string" name="wifi_ca_cert_dialog_preT_abort_text" />
- <item type="string" name="wifi_ca_cert_dialog_preT_message_hint" />
- <item type="string" name="wifi_ca_cert_dialog_preT_message_link" />
- <item type="string" name="wifi_ca_cert_notification_preT_title" />
- <item type="string" name="wifi_ca_cert_notification_preT_message" />
- <item type="string" name="wifi_ca_cert_notification_preT_continue_text" />
- <item type="string" name="wifi_ca_cert_notification_preT_abort_text" />
- <item type="string" name="wifi_tofu_invalid_cert_chain_title" />
- <item type="string" name="wifi_tofu_invalid_cert_chain_message" />
- <item type="string" name="wifi_tofu_invalid_cert_chain_ok_text" />
<!-- Params from strings.xml that can be overlayed -->
<!-- Params from styles.xml that can be overlayed -->
diff --git a/service/ServiceWifiResources/res/values/strings.xml b/service/ServiceWifiResources/res/values/strings.xml
index db331b2e7b..15ffcf0ada 100644
--- a/service/ServiceWifiResources/res/values/strings.xml
+++ b/service/ServiceWifiResources/res/values/strings.xml
@@ -205,9 +205,6 @@
<string name="wifi_ca_cert_notification_title">Network needs to be verified</string>
<string name="wifi_ca_cert_notification_message">Review network details for <xliff:g id="ssid">%1$s</xliff:g> before connecting. Tap to continue.</string>
<string name="wifi_ca_cert_failed_to_install_ca_cert">Certificate installation failed.</string>
- <string name="wifi_tofu_invalid_cert_chain_title">Can\'t connect to <xliff:g id="value">%1$s</xliff:g></string>
- <string name="wifi_tofu_invalid_cert_chain_message">The server certificate chain is invalid.</string>
- <string name="wifi_tofu_invalid_cert_chain_ok_text">OK</string>
<!-- Legacy EAP network dialog and notification text on Pre-T devices. -->
<string name="wifi_ca_cert_dialog_preT_title">Can\'t verify this network</string>
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 0ae71d901f..92cc9ffce6 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -580,6 +580,9 @@ public class ClientModeImpl extends StateMachine implements ClientMode {
@VisibleForTesting
static final int CMD_ACCEPT_EAP_SERVER_CERTIFICATE = BASE + 301;
+ @VisibleForTesting
+ static final int CMD_REJECT_EAP_SERVER_CERTIFICATE = BASE + 302;
+
/* Tracks if suspend optimizations need to be disabled by DHCP,
* screen or due to high perf mode.
* When any of them needs to disable it, we keep the suspend optimizations
@@ -834,11 +837,17 @@ public class ClientModeImpl extends StateMachine implements ClientMode {
@Override
public void onReject(String ssid) {
log("Reject Root CA cert for " + ssid);
+ sendMessage(CMD_REJECT_EAP_SERVER_CERTIFICATE,
+ WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_REJECTED_BY_USER,
+ 0, ssid);
}
@Override
public void onError(String ssid) {
log("Insecure EAP network error for " + ssid);
+ sendMessage(CMD_REJECT_EAP_SERVER_CERTIFICATE,
+ WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE,
+ 0, ssid);
}};
mInsecureEapNetworkHandler = new InsecureEapNetworkHandler(
mContext,
@@ -2252,6 +2261,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode {
return "CMD_UPDATE_LINKPROPERTIES";
case CMD_ACCEPT_EAP_SERVER_CERTIFICATE:
return "CMD_ACCEPT_EAP_SERVER_CERTIFICATE";
+ case CMD_REJECT_EAP_SERVER_CERTIFICATE:
+ return "CMD_REJECT_EAP_SERVER_CERTIFICATE";
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
return "SUPPLICANT_STATE_CHANGE_EVENT";
case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
@@ -4010,21 +4021,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode {
break;
}
}
+ mInsecureEapNetworkHandler.prepareConnection(mTargetWifiConfiguration);
setSelectedRcoiForPasspoint(config);
- if (mInsecureEapNetworkHandler.prepareConnection(mTargetWifiConfiguration)) {
- /* If TOFU is not supported and the user did not approve to connect to an
- insecure network before, do not connect now and instead, display a dialog
- or a notification, and keep network disconnected to avoid sending the
- credentials.
- */
- mInsecureEapNetworkHandler.startUserApprovalIfNecessary(mIsUserSelected);
- reportConnectionAttemptEnd(
- WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED,
- WifiMetricsProto.ConnectionEvent.HLF_NONE,
- WifiMetricsProto.ConnectionEvent.DISCONNECTED_USER_APPROVAL_NEEDED);
- transitionTo(mDisconnectedState);
- break;
- }
connectToNetwork(config);
break;
}
@@ -4268,6 +4266,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode {
break;
}
case CMD_ACCEPT_EAP_SERVER_CERTIFICATE:
+ case CMD_REJECT_EAP_SERVER_CERTIFICATE:
case CMD_START_ROAM:
case CMD_START_RSSI_MONITORING_OFFLOAD:
case CMD_STOP_RSSI_MONITORING_OFFLOAD:
@@ -5374,16 +5373,11 @@ public class ClientModeImpl extends StateMachine implements ClientMode {
}
case WifiMonitor.TOFU_ROOT_CA_CERTIFICATE:
if (null == mTargetWifiConfiguration) break;
- int certificateDepth = message.arg2;
- if (!mInsecureEapNetworkHandler.addPendingCertificate(
+ if (!mInsecureEapNetworkHandler.setPendingCertificate(
mTargetWifiConfiguration.SSID, message.arg2,
(X509Certificate) message.obj)) {
Log.d(TAG, "Cannot set pending cert.");
}
- // Launch user approval upon receiving the server certificate
- if (certificateDepth == 0) {
- mInsecureEapNetworkHandler.startUserApprovalIfNecessary(mIsUserSelected);
- }
break;
default: {
handleStatus = NOT_HANDLED;
@@ -5862,6 +5856,10 @@ public class ClientModeImpl extends StateMachine implements ClientMode {
class L3ProvisioningState extends State {
@Override
public void enter() {
+ if (mInsecureEapNetworkHandler.startUserApprovalIfNecessary(mIsUserSelected)) {
+ return;
+ }
+
startL3Provisioning();
}
@@ -5881,6 +5879,18 @@ public class ClientModeImpl extends StateMachine implements ClientMode {
handleStatus = NOT_HANDLED;
break;
}
+ case CMD_ACCEPT_EAP_SERVER_CERTIFICATE:
+ startL3Provisioning();
+ break;
+ case CMD_REJECT_EAP_SERVER_CERTIFICATE: {
+ int l2FailureReason = message.arg1;
+ reportConnectionAttemptEnd(
+ WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION,
+ WifiMetricsProto.ConnectionEvent.HLF_NONE,
+ l2FailureReason);
+ mWifiNative.disconnect(mInterfaceName);
+ break;
+ }
default: {
handleStatus = NOT_HANDLED;
break;
@@ -6400,12 +6410,6 @@ public class ClientModeImpl extends StateMachine implements ClientMode {
}
break;
}
- case CMD_ACCEPT_EAP_SERVER_CERTIFICATE:
- // Got an approval for a TOFU network, trigger a scan to accelerate the
- // auto-connection.
- logd("User accepted TOFU provided certificate");
- mWifiConnectivityManager.forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
- break;
default: {
handleStatus = NOT_HANDLED;
break;
diff --git a/service/java/com/android/server/wifi/InsecureEapNetworkHandler.java b/service/java/com/android/server/wifi/InsecureEapNetworkHandler.java
index b7389952e0..225d01c7e5 100644
--- a/service/java/com/android/server/wifi/InsecureEapNetworkHandler.java
+++ b/service/java/com/android/server/wifi/InsecureEapNetworkHandler.java
@@ -40,8 +40,6 @@ import com.android.server.wifi.util.NativeUtil;
import com.android.wifi.resources.R;
import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.List;
/** This class is used to handle insecure EAP networks. */
public class InsecureEapNetworkHandler {
@@ -73,27 +71,18 @@ public class InsecureEapNetworkHandler {
private final String mInterfaceName;
private final Handler mHandler;
- // The latest connecting configuration from the caller, it is updated on calling
- // prepareConnection() always. This is used to ensure that current TOFU config is aligned
- // with the caller connecting config.
@NonNull
- private WifiConfiguration mConnectingConfig = null;
- // The connecting configuration which is a valid TOFU configuration, it is updated
- // only when the connecting configuration is a valid TOFU configuration and used
- // by later TOFU procedure.
- @NonNull
- private WifiConfiguration mCurrentTofuConfig = null;
- private int mPendingRootCaCertDepth = -1;
+ private WifiConfiguration mCurConfig = null;
+ private int mPendingCaCertDepth = -1;
@Nullable
- private X509Certificate mPendingRootCaCert = null;
+ private X509Certificate mPendingCaCert = null;
@Nullable
private X509Certificate mPendingServerCert = null;
- // This is updated on setting a pending server cert.
- private CertificateSubjectInfo mPendingServerCertSubjectInfo = null;
- // This is updated on setting a pending server cert.
- private CertificateSubjectInfo mPendingServerCertIssuerInfo = null;
- // Record the whole server cert chain from Root CA to the server cert.
- private List<X509Certificate> mServerCertChain = new ArrayList<>();
+ // This is updated on setting a pending CA cert.
+ private CertificateSubjectInfo mPendingCaCertSubjectInfo = null;
+ // This is updated on setting a pending CA cert.
+ private CertificateSubjectInfo mPendingCaCertIssuerInfo = null;
+ @Nullable
private WifiDialogManager.DialogHandle mTofuAlertDialog = null;
private boolean mIsCertNotificationReceiverRegistered = false;
@@ -148,17 +137,16 @@ public class InsecureEapNetworkHandler {
* uses Server Cert, without a valid Root CA certificate or user approval.
*
* @param config the running wifi configuration.
- * @return true if user needs to be notified about an insecure network but TOFU is not supported
- * by the device, or false otherwise.
*/
- public boolean prepareConnection(@NonNull WifiConfiguration config) {
- if (null == config) return false;
- mConnectingConfig = config;
+ public void prepareConnection(@NonNull WifiConfiguration config) {
+ if (null == config) return;
- if (!config.isEnterprise()) return false;
+ if (!config.isEnterprise()) return;
WifiEnterpriseConfig entConfig = config.enterpriseConfig;
- if (!entConfig.isEapMethodServerCertUsed()) return false;
- if (entConfig.hasCaCertificate()) return false;
+ if (!entConfig.isEapMethodServerCertUsed()) return;
+ if (entConfig.hasCaCertificate()) return;
+
+ clearConnection();
Log.d(TAG, "prepareConnection: isTofuSupported=" + mIsTrustOnFirstUseSupported
+ ", isInsecureEapNetworkAllowed=" + mIsInsecureEnterpriseConfigurationAllowed
@@ -167,115 +155,71 @@ public class InsecureEapNetworkHandler {
// If TOFU is not supported or insecure EAP network is allowed without TOFU enabled,
// return to skip the dialog if this network is approved before.
if (entConfig.isUserApproveNoCaCert()) {
- if (!mIsTrustOnFirstUseSupported) return false;
+ if (!mIsTrustOnFirstUseSupported) return;
if (mIsInsecureEnterpriseConfigurationAllowed
&& !entConfig.isTrustOnFirstUseEnabled()) {
- return false;
+ return;
}
}
- if (mIsTrustOnFirstUseSupported) {
- /**
- * Clear the user credentials from this copy of the configuration object.
- * Supplicant will start the phase-1 TLS session to acquire the server certificate chain
- * which will be provided to the framework. Then since the callbacks for identity and
- * password requests are not populated, it will fail the connection and disconnect.
- * This will allow the user to review the certificates at their own pace, and a
- * reconnection would automatically take place with full verification of the chain once
- * they approve.
- */
- if (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS
- || config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP) {
- config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
- config.enterpriseConfig.setIdentity(null);
- config.enterpriseConfig.setPassword(null);
- } else if (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS) {
- config.enterpriseConfig.setClientCertificateAlias(null);
- }
- }
- mCurrentTofuConfig = config;
- mServerCertChain.clear();
- dismissDialogAndNotification();
+ mCurConfig = config;
registerCertificateNotificationReceiver();
- if (!mIsTrustOnFirstUseSupported) {
- /**
- * Devices with no TOFU support, do not connect to the network until the user is
- * aware that the network is insecure, and approves the connection.
- */
- putNetworkOnHold(false);
- } else {
- // Remove cached PMK in the framework and supplicant to avoid skipping the EAP flow.
- clearNativeData();
- Log.d(TAG, "Remove native cached data and networks for TOFU.");
- }
- return !mIsTrustOnFirstUseSupported;
+ // Remove cached PMK in the framework and supplicant to avoid
+ // skipping the EAP flow.
+ clearNativeData();
+ Log.d(TAG, "Remove native cached data and networks for TOFU.");
}
- /**
- * Do necessary clean up on stopping client mode.
- */
- public void cleanup() {
- dismissDialogAndNotification();
+ /** Clear data on disconnecting a connection. */
+ private void clearConnection() {
unregisterCertificateNotificationReceiver();
+ dismissDialogAndNotification();
clearInternalData();
}
/**
- * Stores a received certificate for later use.
+ * Store the received certifiate for later use.
*
* @param ssid the target network SSID.
* @param depth the depth of this cert. The Root CA should be 0 or
* a positive number, and the server cert is 0.
- * @param cert a certificate from the server.
+ * @param cert the Root CA certificate from the server.
* @return true if the cert is cached; otherwise, false.
*/
- public boolean addPendingCertificate(@NonNull String ssid, int depth,
+ public boolean setPendingCertificate(@NonNull String ssid, int depth,
@NonNull X509Certificate cert) {
- String configProfileKey = mCurrentTofuConfig != null
- ? mCurrentTofuConfig.getProfileKey() : "null";
Log.d(TAG, "setPendingCertificate: " + "ssid=" + ssid + " depth=" + depth
- + " current config=" + configProfileKey);
+ + " current config=" + mCurConfig);
if (TextUtils.isEmpty(ssid)) return false;
- if (null == mCurrentTofuConfig) return false;
- if (!TextUtils.equals(ssid, mCurrentTofuConfig.SSID)) return false;
+ if (null == mCurConfig) return false;
+ if (!TextUtils.equals(ssid, mCurConfig.SSID)) return false;
if (null == cert) return false;
if (depth < 0) return false;
-
- if (depth == 0) {
- // Disable network selection upon receiving the server certificate
- putNetworkOnHold(true);
- }
-
- if (!mServerCertChain.contains(cert)) {
- mServerCertChain.add(cert);
- }
-
// 0 is the tail, i.e. the server cert.
if (depth == 0 && null == mPendingServerCert) {
mPendingServerCert = cert;
Log.d(TAG, "Pending server certificate: " + mPendingServerCert);
- mPendingServerCertSubjectInfo = CertificateSubjectInfo.parse(
- cert.getSubjectX500Principal().getName());
- if (null == mPendingServerCertSubjectInfo) {
- Log.e(TAG, "CA cert has no valid subject.");
- return false;
- }
- mPendingServerCertIssuerInfo = CertificateSubjectInfo.parse(
- cert.getIssuerX500Principal().getName());
- if (null == mPendingServerCertIssuerInfo) {
- Log.e(TAG, "CA cert has no valid issuer.");
- return false;
- }
}
-
- // Root or intermediate cert.
- if (depth < mPendingRootCaCertDepth) {
+ if (depth < mPendingCaCertDepth) {
Log.d(TAG, "Ignore intermediate cert." + cert);
return true;
}
- mPendingRootCaCertDepth = depth;
- mPendingRootCaCert = cert;
- Log.d(TAG, "Pending Root CA certificate: " + mPendingRootCaCert);
+
+ mPendingCaCertSubjectInfo = CertificateSubjectInfo.parse(
+ cert.getSubjectDN().getName());
+ if (null == mPendingCaCertSubjectInfo) {
+ Log.e(TAG, "CA cert has no valid subject.");
+ return false;
+ }
+ mPendingCaCertIssuerInfo = CertificateSubjectInfo.parse(
+ cert.getIssuerDN().getName());
+ if (null == mPendingCaCertIssuerInfo) {
+ Log.e(TAG, "CA cert has no valid issuer.");
+ return false;
+ }
+ mPendingCaCertDepth = depth;
+ mPendingCaCert = cert;
+ Log.d(TAG, "Pending Root CA certificate: " + mPendingCaCert);
return true;
}
@@ -300,89 +244,31 @@ public class InsecureEapNetworkHandler {
* @return true if the user approval is needed; otherwise, false.
*/
public boolean startUserApprovalIfNecessary(boolean isUserSelected) {
- if (null == mConnectingConfig || null == mCurrentTofuConfig) return false;
- if (mConnectingConfig.networkId != mCurrentTofuConfig.networkId) return false;
+ if (null == mCurConfig) return false;
+ if (!mCurConfig.isEnterprise()) return false;
+ WifiEnterpriseConfig entConfig = mCurConfig.enterpriseConfig;
+ if (!entConfig.isEapMethodServerCertUsed()) return false;
+ if (entConfig.hasCaCertificate()) return false;
// If Trust On First Use is supported and insecure enterprise configuration
// is not allowed, TOFU must be used for an Enterprise network without certs.
if (mIsTrustOnFirstUseSupported && !mIsInsecureEnterpriseConfigurationAllowed
- && !mCurrentTofuConfig.enterpriseConfig.isTrustOnFirstUseEnabled()) {
+ && !mCurConfig.enterpriseConfig.isTrustOnFirstUseEnabled()) {
Log.d(TAG, "Trust On First Use is not enabled.");
- handleError(mCurrentTofuConfig.SSID);
+ handleError(mCurConfig.SSID);
return true;
}
if (useTrustOnFirstUse()) {
- if (null == mPendingRootCaCert) {
- Log.e(TAG, "No valid CA cert for TLS-based connection.");
- handleError(mCurrentTofuConfig.SSID);
+ if (null == mPendingCaCert) {
+ Log.d(TAG, "No valid CA cert for TLS-based connection.");
+ handleError(mCurConfig.SSID);
return true;
} else if (null == mPendingServerCert) {
- Log.e(TAG, "No valid Server cert for TLS-based connection.");
- handleError(mCurrentTofuConfig.SSID);
- return true;
- } else if (!isServerCertChainValid()) {
- Log.e(TAG, "Server cert chain is invalid.");
- String title = mContext.getString(R.string.wifi_tofu_invalid_cert_chain_title,
- mCurrentTofuConfig.SSID);
- String message = mContext.getString(R.string.wifi_tofu_invalid_cert_chain_message);
- String okButtonText = mContext.getString(
- R.string.wifi_tofu_invalid_cert_chain_ok_text);
-
- handleError(mCurrentTofuConfig.SSID);
-
- if (TextUtils.isEmpty(title) || TextUtils.isEmpty(message)) return true;
-
- if (isUserSelected) {
- mTofuAlertDialog = mWifiDialogManager.createSimpleDialog(
- title,
- message,
- null /* positiveButtonText */,
- null /* negativeButtonText */,
- okButtonText,
- new WifiDialogManager.SimpleDialogCallback() {
- @Override
- public void onPositiveButtonClicked() {
- // Not used.
- }
-
- @Override
- public void onNegativeButtonClicked() {
- // Not used.
- }
-
- @Override
- public void onNeutralButtonClicked() {
- // Not used.
- }
-
- @Override
- public void onCancelled() {
- // Not used.
- }
- },
- new WifiThreadRunner(mHandler));
- mTofuAlertDialog.launchDialog();
- } else {
- Notification.Builder builder = mFacade.makeNotificationBuilder(mContext,
- WifiService.NOTIFICATION_NETWORK_ALERTS)
- .setSmallIcon(
- Icon.createWithResource(mContext.getWifiOverlayApkPkgName(),
- com.android.wifi.resources.R
- .drawable.stat_notify_wifi_in_range))
- .setContentTitle(title)
- .setContentText(message)
- .setStyle(new Notification.BigTextStyle().bigText(message))
- .setColor(mContext.getResources().getColor(
- android.R.color.system_notification_accent_color));
- mNotificationManager.notify(SystemMessage.NOTE_SERVER_CA_CERTIFICATE,
- builder.build());
- }
+ Log.d(TAG, "No valid Server cert for TLS-based connection.");
+ handleError(mCurConfig.SSID);
return true;
}
- } else if (mIsInsecureEnterpriseConfigurationAllowed) {
- Log.i(TAG, "networks without the server cert are allowed, skip it.");
- return false;
}
Log.d(TAG, "startUserApprovalIfNecessaryForInsecureEapNetwork: mIsUserSelected="
@@ -396,56 +282,13 @@ public class InsecureEapNetworkHandler {
return true;
}
- /**
- * Disable network selection, disconnect if necessary, and clear PMK cache
- */
- private void putNetworkOnHold(boolean needToDisconnect) {
- // Disable network selection upon receiving the server certificate
- mWifiConfigManager.updateNetworkSelectionStatus(mCurrentTofuConfig.networkId,
- WifiConfiguration.NetworkSelectionStatus
- .DISABLED_BY_WIFI_MANAGER);
-
- // Force disconnect and clear PMK cache to avoid supplicant reconnection
- if (needToDisconnect) mWifiNative.disconnect(mInterfaceName);
- clearNativeData();
- }
-
- private boolean isServerCertChainValid() {
- if (mServerCertChain.size() == 0) return false;
-
- X509Certificate parentCert = null;
- for (X509Certificate cert: mServerCertChain) {
- String subject = cert.getSubjectX500Principal().getName();
- String issuer = cert.getIssuerX500Principal().getName();
- boolean isCa = cert.getBasicConstraints() >= 0;
- Log.d(TAG, "Subject: " + subject + ", Issuer: " + issuer + ", isCA: " + isCa);
-
- if (parentCert == null) {
- // The root cert, it should be a CA cert or a self-signed cert.
- if (!isCa && !subject.equals(issuer)) {
- Log.e(TAG, "The root cert is not a CA cert or a self-signed cert.");
- return false;
- }
- } else {
- // The issuer of intermediate cert of the leaf cert should be
- // the same as the subject of its parent cert.
- if (!parentCert.getSubjectX500Principal().getName().equals(issuer)) {
- Log.e(TAG, "The issuer does not match the subject of its parent.");
- return false;
- }
- }
- parentCert = cert;
- }
- return true;
- }
-
private boolean useTrustOnFirstUse() {
return mIsTrustOnFirstUseSupported
- && mCurrentTofuConfig.enterpriseConfig.isTrustOnFirstUseEnabled();
+ && mCurConfig.enterpriseConfig.isTrustOnFirstUseEnabled();
}
private void registerCertificateNotificationReceiver() {
- unregisterCertificateNotificationReceiver();
+ if (mIsCertNotificationReceiverRegistered) return;
IntentFilter filter = new IntentFilter();
if (useTrustOnFirstUse()) {
@@ -470,22 +313,21 @@ public class InsecureEapNetworkHandler {
if (!isConnectionValid(ssid)) return;
if (!useTrustOnFirstUse()) {
- mWifiConfigManager.setUserApproveNoCaCert(mCurrentTofuConfig.networkId, true);
+ mWifiConfigManager.setUserApproveNoCaCert(mCurConfig.networkId, true);
} else {
- if (null == mPendingRootCaCert || null == mPendingServerCert) {
+ if (null == mPendingCaCert || null == mPendingServerCert) {
handleError(ssid);
return;
}
if (!mWifiConfigManager.updateCaCertificate(
- mCurrentTofuConfig.networkId, mPendingRootCaCert, mPendingServerCert)) {
+ mCurConfig.networkId, mPendingCaCert, mPendingServerCert)) {
// The user approved this network,
// keep the connection regardless of the result.
- Log.e(TAG, "Cannot update CA cert to network " + mCurrentTofuConfig.getProfileKey()
- + ", CA cert = " + mPendingRootCaCert);
+ Log.e(TAG, "Cannot update CA cert to network " + mCurConfig.getProfileKey()
+ + ", CA cert = " + mPendingCaCert);
}
}
- mWifiConfigManager.updateNetworkSelectionStatus(mCurrentTofuConfig.networkId,
- WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE);
+ mWifiConfigManager.allowAutojoin(mCurConfig.networkId, true);
dismissDialogAndNotification();
clearInternalData();
@@ -496,8 +338,7 @@ public class InsecureEapNetworkHandler {
void handleReject(@NonNull String ssid) {
if (!isConnectionValid(ssid)) return;
- mWifiConfigManager.updateNetworkSelectionStatus(mCurrentTofuConfig.networkId,
- WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER);
+ mWifiConfigManager.allowAutojoin(mCurConfig.networkId, false);
dismissDialogAndNotification();
clearInternalData();
clearNativeData();
@@ -506,11 +347,6 @@ public class InsecureEapNetworkHandler {
}
private void handleError(@Nullable String ssid) {
- if (mCurrentTofuConfig != null) {
- mWifiConfigManager.updateNetworkSelectionStatus(mCurrentTofuConfig.networkId,
- WifiConfiguration.NetworkSelectionStatus
- .DISABLED_BY_WIFI_MANAGER);
- }
dismissDialogAndNotification();
clearInternalData();
clearNativeData();
@@ -519,9 +355,9 @@ public class InsecureEapNetworkHandler {
}
private void askForUserApprovalForCaCertificate() {
- if (mCurrentTofuConfig == null || TextUtils.isEmpty(mCurrentTofuConfig.SSID)) return;
+ if (mCurConfig == null || TextUtils.isEmpty(mCurConfig.SSID)) return;
if (useTrustOnFirstUse()) {
- if (null == mPendingRootCaCert || null == mPendingServerCert) {
+ if (null == mPendingCaCert || null == mPendingServerCert) {
Log.e(TAG, "Cannot launch a dialog for TOFU without "
+ "a valid pending CA certificate.");
return;
@@ -539,42 +375,39 @@ public class InsecureEapNetworkHandler {
? mContext.getString(R.string.wifi_ca_cert_dialog_abort_text)
: mContext.getString(R.string.wifi_ca_cert_dialog_preT_abort_text);
- String message;
+ String message = null;
String messageUrl = null;
int messageUrlStart = 0;
int messageUrlEnd = 0;
if (useTrustOnFirstUse()) {
+ String signature = NativeUtil.hexStringFromByteArray(
+ mPendingCaCert.getSignature());
StringBuilder contentBuilder = new StringBuilder()
.append(mContext.getString(R.string.wifi_ca_cert_dialog_message_hint))
.append(mContext.getString(
R.string.wifi_ca_cert_dialog_message_server_name_text,
- mPendingServerCertSubjectInfo.commonName))
+ mPendingCaCertSubjectInfo.commonName))
.append(mContext.getString(
R.string.wifi_ca_cert_dialog_message_issuer_name_text,
- mPendingServerCertIssuerInfo.commonName));
- if (!TextUtils.isEmpty(mPendingServerCertSubjectInfo.organization)) {
+ mPendingCaCertIssuerInfo.commonName));
+ if (!TextUtils.isEmpty(mPendingCaCertSubjectInfo.organization)) {
contentBuilder.append(mContext.getString(
R.string.wifi_ca_cert_dialog_message_organization_text,
- mPendingServerCertSubjectInfo.organization));
+ mPendingCaCertSubjectInfo.organization));
}
- if (!TextUtils.isEmpty(mPendingServerCertSubjectInfo.email)) {
+ if (!TextUtils.isEmpty(mPendingCaCertSubjectInfo.email)) {
contentBuilder.append(mContext.getString(
R.string.wifi_ca_cert_dialog_message_contact_text,
- mPendingServerCertSubjectInfo.email));
- }
- byte[] signature = mPendingServerCert.getSignature();
- if (signature != null) {
- String signatureString = NativeUtil.hexStringFromByteArray(signature);
- if (signatureString.length() > 16) {
- signatureString = signatureString.substring(0, 16);
- }
- contentBuilder.append(mContext.getString(
- R.string.wifi_ca_cert_dialog_message_signature_name_text, signatureString));
+ mPendingCaCertSubjectInfo.email));
}
+ contentBuilder
+ .append(mContext.getString(
+ R.string.wifi_ca_cert_dialog_message_signature_name_text,
+ signature.substring(0, 16)));
message = contentBuilder.toString();
} else {
String hint = mContext.getString(
- R.string.wifi_ca_cert_dialog_preT_message_hint, mCurrentTofuConfig.SSID);
+ R.string.wifi_ca_cert_dialog_preT_message_hint, mCurConfig.SSID);
String linkText = mContext.getString(
R.string.wifi_ca_cert_dialog_preT_message_link);
message = hint + " " + linkText;
@@ -594,35 +427,23 @@ public class InsecureEapNetworkHandler {
new WifiDialogManager.SimpleDialogCallback() {
@Override
public void onPositiveButtonClicked() {
- if (mCurrentTofuConfig == null) {
- return;
- }
- handleAccept(mCurrentTofuConfig.SSID);
+ handleAccept(mCurConfig.SSID);
}
@Override
public void onNegativeButtonClicked() {
- if (mCurrentTofuConfig == null) {
- return;
- }
- handleReject(mCurrentTofuConfig.SSID);
+ handleReject(mCurConfig.SSID);
}
@Override
public void onNeutralButtonClicked() {
// Not used.
- if (mCurrentTofuConfig == null) {
- return;
- }
- handleReject(mCurrentTofuConfig.SSID);
+ handleReject(mCurConfig.SSID);
}
@Override
public void onCancelled() {
- if (mCurrentTofuConfig == null) {
- return;
- }
- handleReject(mCurrentTofuConfig.SSID);
+ handleReject(mCurConfig.SSID);
}
},
new WifiThreadRunner(mHandler));
@@ -639,16 +460,16 @@ public class InsecureEapNetworkHandler {
}
private void notifyUserForCaCertificate() {
- if (mCurrentTofuConfig == null) return;
+ if (mCurConfig == null) return;
if (useTrustOnFirstUse()) {
- if (null == mPendingRootCaCert) return;
+ if (null == mPendingCaCert) return;
if (null == mPendingServerCert) return;
}
dismissDialogAndNotification();
PendingIntent tapPendingIntent;
if (useTrustOnFirstUse()) {
- tapPendingIntent = genCaCertNotifIntent(ACTION_CERT_NOTIF_TAP, mCurrentTofuConfig.SSID);
+ tapPendingIntent = genCaCertNotifIntent(ACTION_CERT_NOTIF_TAP, mCurConfig.SSID);
} else {
Intent openLinkIntent = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse(mCaCertHelpLink))
@@ -661,10 +482,9 @@ public class InsecureEapNetworkHandler {
? mContext.getString(R.string.wifi_ca_cert_notification_title)
: mContext.getString(R.string.wifi_ca_cert_notification_preT_title);
String content = useTrustOnFirstUse()
- ? mContext.getString(R.string.wifi_ca_cert_notification_message,
- mCurrentTofuConfig.SSID)
+ ? mContext.getString(R.string.wifi_ca_cert_notification_message, mCurConfig.SSID)
: mContext.getString(R.string.wifi_ca_cert_notification_preT_message,
- mCurrentTofuConfig.SSID);
+ mCurConfig.SSID);
Notification.Builder builder = mFacade.makeNotificationBuilder(mContext,
WifiService.NOTIFICATION_NETWORK_ALERTS)
.setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(),
@@ -682,13 +502,11 @@ public class InsecureEapNetworkHandler {
Notification.Action acceptAction = new Notification.Action.Builder(
null /* icon */,
mContext.getString(R.string.wifi_ca_cert_dialog_preT_continue_text),
- genCaCertNotifIntent(ACTION_CERT_NOTIF_ACCEPT, mCurrentTofuConfig.SSID))
- .build();
+ genCaCertNotifIntent(ACTION_CERT_NOTIF_ACCEPT, mCurConfig.SSID)).build();
Notification.Action rejectAction = new Notification.Action.Builder(
null /* icon */,
mContext.getString(R.string.wifi_ca_cert_dialog_preT_abort_text),
- genCaCertNotifIntent(ACTION_CERT_NOTIF_REJECT, mCurrentTofuConfig.SSID))
- .build();
+ genCaCertNotifIntent(ACTION_CERT_NOTIF_REJECT, mCurConfig.SSID)).build();
builder.addAction(rejectAction).addAction(acceptAction);
}
mNotificationManager.notify(SystemMessage.NOTE_SERVER_CA_CERTIFICATE, builder.build());
@@ -703,18 +521,18 @@ public class InsecureEapNetworkHandler {
}
private void clearInternalData() {
- mPendingRootCaCertDepth = -1;
- mPendingRootCaCert = null;
+ mPendingCaCertDepth = -1;
+ mPendingCaCert = null;
mPendingServerCert = null;
- mPendingServerCertSubjectInfo = null;
- mPendingServerCertIssuerInfo = null;
- mCurrentTofuConfig = null;
+ mPendingCaCertSubjectInfo = null;
+ mPendingCaCertIssuerInfo = null;
+ mCurConfig = null;
}
private void clearNativeData() {
// PMK should be cleared or it would skip EAP flow next time.
- if (null != mCurrentTofuConfig) {
- mWifiNative.removeNetworkCachedData(mCurrentTofuConfig.networkId);
+ if (null != mCurConfig) {
+ mWifiNative.removeNetworkCachedData(mCurConfig.networkId);
}
// remove network so that supplicant's PMKSA cache is cleared
mWifiNative.removeAllNetworks(mInterfaceName);
@@ -733,13 +551,13 @@ public class InsecureEapNetworkHandler {
// If condition #2 occurs, clear existing data and notify the client mode
// via onError callback.
private boolean isConnectionValid(@Nullable String ssid) {
- if (TextUtils.isEmpty(ssid) || null == mCurrentTofuConfig) {
+ if (TextUtils.isEmpty(ssid) || null == mCurConfig) {
handleError(null);
return false;
}
- if (!TextUtils.equals(ssid, mCurrentTofuConfig.SSID)) {
- Log.w(TAG, "Target SSID " + mCurrentTofuConfig.SSID
+ if (!TextUtils.equals(ssid, mCurConfig.SSID)) {
+ Log.w(TAG, "Target SSID " + mCurConfig.SSID
+ " is different from TOFU returned SSID" + ssid);
return false;
}
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 6a065ce055..d63246acb9 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -528,6 +528,9 @@ public class WifiServiceImpl extends BaseWifiService {
if (!mWifiConfigManager.loadFromStore()) {
Log.e(TAG, "Failed to load from config store");
}
+ if (!mWifiGlobals.isInsecureEnterpriseConfigurationAllowed()) {
+ mWifiConfigManager.updateTrustOnFirstUseFlag(isTrustOnFirstUseSupported());
+ }
mWifiConfigManager.incrementNumRebootsSinceLastUse();
// config store is read, check if verbose logging is enabled.
enableVerboseLoggingInternal(
@@ -792,10 +795,6 @@ public class WifiServiceImpl extends BaseWifiService {
mLohsSoftApTracker.handleBootCompleted();
mWifiInjector.getSarManager().handleBootCompleted();
mIsBootComplete = true;
- // HW capabilities is ready after boot completion.
- if (!mWifiGlobals.isInsecureEnterpriseConfigurationAllowed()) {
- mWifiConfigManager.updateTrustOnFirstUseFlag(isTrustOnFirstUseSupported());
- }
});
}
diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto
index 871eb2c750..09a596f984 100644
--- a/service/proto/src/metrics.proto
+++ b/service/proto/src/metrics.proto
@@ -1047,9 +1047,6 @@ message ConnectionEvent {
// The reason code if a user rejects this connection.
AUTH_FAILURE_REJECTED_BY_USER = 7;
-
- // The reason code if an insecure Enterprise connection requires user's approval
- DISCONNECTED_USER_APPROVAL_NEEDED = 8;
}
// Entity that recommended connecting to this network.
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index e2309e9ce4..ca8f5b031c 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -7860,18 +7860,11 @@ public class ClientModeImplTest extends WifiBaseTest {
WifiEnterpriseConfig.Eap.TLS, WifiEnterpriseConfig.Phase2.NONE));
eapTlsConfig.networkId = FRAMEWORK_NETWORK_ID;
eapTlsConfig.SSID = TEST_SSID;
- if (isAtLeastT && isTrustOnFirstUseSupported) {
+ if (isAtLeastT) {
eapTlsConfig.enterpriseConfig.enableTrustOnFirstUse(true);
- when(mInsecureEapNetworkHandler.prepareConnection(any(WifiConfiguration.class)))
- .thenReturn(false);
- } else {
- when(mInsecureEapNetworkHandler.prepareConnection(any(WifiConfiguration.class)))
- .thenReturn(true);
}
eapTlsConfig.enterpriseConfig.setCaPath("");
eapTlsConfig.enterpriseConfig.setDomainSuffixMatch("");
- eapTlsConfig.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS);
- eapTlsConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
initializeAndAddNetworkAndVerifySuccess(eapTlsConfig);
@@ -7886,31 +7879,31 @@ public class ClientModeImplTest extends WifiBaseTest {
}
verify(mInsecureEapNetworkHandler).prepareConnection(eq(eapTlsConfig));
- if (isTrustOnFirstUseSupported) {
- mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
- new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR,
- SupplicantState.ASSOCIATED));
- mLooper.dispatchAll();
+ mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
+ new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR,
+ SupplicantState.ASSOCIATED));
+ mLooper.dispatchAll();
+ if (isTrustOnFirstUseSupported) {
mCmi.sendMessage(WifiMonitor.TOFU_ROOT_CA_CERTIFICATE,
FRAMEWORK_NETWORK_ID, 0, FakeKeys.CA_CERT0);
mLooper.dispatchAll();
- verify(mInsecureEapNetworkHandler).addPendingCertificate(
+ verify(mInsecureEapNetworkHandler).setPendingCertificate(
eq(eapTlsConfig.SSID), eq(0), eq(FakeKeys.CA_CERT0));
-
- // Adding a certificate in depth 0 will cause a disconnection when TOFU is supported
- DisconnectEventInfo disconnectEventInfo =
- new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 3, true);
- mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
- mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
- new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR,
- SupplicantState.DISCONNECTED));
- mLooper.dispatchAll();
}
+ mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
+ new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false));
+ mLooper.dispatchAll();
+
+ mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
+ new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR,
+ SupplicantState.COMPLETED));
+ mLooper.dispatchAll();
+
verify(mInsecureEapNetworkHandler).startUserApprovalIfNecessary(eq(isUserSelected));
- // In any case, we end up in the disconnected state
- assertEquals("DisconnectedState", getCurrentState().getName());
+ assertEquals("L3ProvisioningState", getCurrentState().getName());
+
return eapTlsConfig;
}
@@ -7926,22 +7919,9 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onAccept(testConfig.SSID);
mLooper.dispatchAll();
- verify(mWifiConnectivityManager).forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
- }
-
- /**
- * Verify logic when Trust On First Use is not supported
- * - This network is selected by a user.
- * - Network gets connected
- */
- @Test
- public void verifyTrustOnFirstUseAcceptWhenConnectByUserNoTofu() throws Exception {
- assumeTrue(SdkLevel.isAtLeastT());
- WifiConfiguration testConfig = setupTrustOnFirstUse(true, false, true);
-
- mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onAccept(testConfig.SSID);
+ injectDhcpSuccess();
mLooper.dispatchAll();
- verify(mWifiConnectivityManager).forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
+ assertEquals("L3ConnectedState", getCurrentState().getName());
}
/**
@@ -7956,13 +7936,7 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onReject(testConfig.SSID);
mLooper.dispatchAll();
- verify(mWifiConnectivityManager, never())
- .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
- verify(mWifiMetrics).endConnectionEvent(
- any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
- eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
- eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN),
- anyInt());
+ verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
}
/**
@@ -7977,13 +7951,7 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onError(testConfig.SSID);
mLooper.dispatchAll();
- verify(mWifiConnectivityManager, never())
- .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
- verify(mWifiMetrics).endConnectionEvent(
- any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
- eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
- eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN),
- anyInt());
+ verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
}
/**
@@ -7999,7 +7967,9 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onAccept(testConfig.SSID);
mLooper.dispatchAll();
- verify(mWifiConnectivityManager).forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
+ injectDhcpSuccess();
+ mLooper.dispatchAll();
+ assertEquals("L3ConnectedState", getCurrentState().getName());
}
/**
@@ -8015,13 +7985,7 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onReject(testConfig.SSID);
mLooper.dispatchAll();
- verify(mWifiConnectivityManager, never())
- .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
- verify(mWifiMetrics).endConnectionEvent(
- any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
- eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
- eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN),
- anyInt());
+ verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
}
/**
@@ -8036,13 +8000,7 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onError(testConfig.SSID);
mLooper.dispatchAll();
- verify(mWifiConnectivityManager, never())
- .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
- verify(mWifiMetrics).endConnectionEvent(
- any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
- eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
- eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN),
- anyInt());
+ verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
}
/**
@@ -8057,7 +8015,9 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onAccept(testConfig.SSID);
mLooper.dispatchAll();
- verify(mWifiConnectivityManager).forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
+ injectDhcpSuccess();
+ mLooper.dispatchAll();
+ assertEquals("L3ConnectedState", getCurrentState().getName());
}
/**
@@ -8072,13 +8032,7 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onReject(testConfig.SSID);
mLooper.dispatchAll();
- verify(mWifiConnectivityManager, never())
- .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
- verify(mWifiMetrics).endConnectionEvent(
- any(), eq(WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED),
- eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
- eq(WifiMetricsProto.ConnectionEvent.DISCONNECTED_USER_APPROVAL_NEEDED),
- anyInt());
+ verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
}
/**
@@ -8093,13 +8047,7 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onError(testConfig.SSID);
mLooper.dispatchAll();
- verify(mWifiConnectivityManager, never())
- .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
- verify(mWifiMetrics).endConnectionEvent(
- any(), eq(WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED),
- eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
- eq(WifiMetricsProto.ConnectionEvent.DISCONNECTED_USER_APPROVAL_NEEDED),
- anyInt());
+ verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
}
/**
@@ -8113,8 +8061,9 @@ public class ClientModeImplTest extends WifiBaseTest {
WifiConfiguration testConfig = setupLegacyEapNetworkTest(false);
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onAccept(testConfig.SSID);
+ injectDhcpSuccess();
mLooper.dispatchAll();
- verify(mWifiConnectivityManager).forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
+ assertEquals("L3ConnectedState", getCurrentState().getName());
}
/**
@@ -8129,14 +8078,9 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onReject(testConfig.SSID);
mLooper.dispatchAll();
+
verify(mFrameworkFacade, never()).makeAlertDialogBuilder(any());
- verify(mWifiConnectivityManager, never())
- .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
- verify(mWifiMetrics).endConnectionEvent(
- any(), eq(WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED),
- eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
- eq(WifiMetricsProto.ConnectionEvent.DISCONNECTED_USER_APPROVAL_NEEDED),
- anyInt());
+ verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
}
/**
@@ -8151,13 +8095,7 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onError(testConfig.SSID);
mLooper.dispatchAll();
- verify(mWifiConnectivityManager, never())
- .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
- verify(mWifiMetrics).endConnectionEvent(
- any(), eq(WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED),
- eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
- eq(WifiMetricsProto.ConnectionEvent.DISCONNECTED_USER_APPROVAL_NEEDED),
- anyInt());
+ verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
}
private void setScanResultWithMloInfo() {
diff --git a/service/tests/wifitests/src/com/android/server/wifi/InsecureEapNetworkHandlerTest.java b/service/tests/wifitests/src/com/android/server/wifi/InsecureEapNetworkHandlerTest.java
index 6e2e67a8a2..aed3753ffc 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/InsecureEapNetworkHandlerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/InsecureEapNetworkHandlerTest.java
@@ -17,18 +17,14 @@
package com.android.server.wifi;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.validateMockitoUsage;
@@ -41,16 +37,11 @@ import android.content.Intent;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiContext;
import android.net.wifi.WifiEnterpriseConfig;
-import android.net.wifi.util.HexEncoding;
import android.os.Handler;
-import android.text.TextUtils;
import androidx.test.filters.SmallTest;
import com.android.modules.utils.build.SdkLevel;
-import com.android.server.wifi.util.CertificateSubjectInfo;
-import com.android.server.wifi.util.NativeUtil;
-import com.android.wifi.resources.R;
import org.junit.After;
import org.junit.Before;
@@ -60,13 +51,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
-import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
-import javax.security.auth.x500.X500Principal;
-
/**
* Unit tests for {@link com.android.server.wifi.InsecureEapNetworkHandlerTest}.
*/
@@ -78,9 +65,7 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
private static final int ACTION_TAP = 2;
private static final String WIFI_IFACE_NAME = "wlan-test-9";
private static final int FRAMEWORK_NETWORK_ID = 2;
- private static final String TEST_SSID = "\"test_ssid\"";
- private static final String TEST_IDENTITY = "userid";
- private static final String TEST_PASSWORD = "myPassWord!";
+ private static final String TEST_SSID = "test_ssid";
@Mock WifiContext mContext;
@Mock WifiConfigManager mWifiConfigManager;
@@ -109,34 +94,11 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
when(mContext.getString(anyInt())).thenReturn("TestString");
when(mContext.getString(anyInt(), any())).thenReturn("TestStringWithArgument");
when(mContext.getText(anyInt())).thenReturn("TestStr");
- when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_issuer_name_text),
- anyString()))
- .thenAnswer((Answer<String>) invocation ->
- "Issuer Name:\n" + invocation.getArguments()[1] + "\n\n");
- when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_server_name_text),
- anyString()))
- .thenAnswer((Answer<String>) invocation ->
- "Server Name:\n" + invocation.getArguments()[1] + "\n\n");
- when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_organization_text),
- anyString()))
- .thenAnswer((Answer<String>) invocation ->
- "Organization:\n" + invocation.getArguments()[1] + "\n\n");
- when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_contact_text),
- anyString()))
- .thenAnswer((Answer<String>) invocation ->
- "Contact:\n" + invocation.getArguments()[1] + "\n\n");
- when(mContext.getString(eq(R.string.wifi_ca_cert_dialog_message_signature_name_text),
- anyString()))
- .thenAnswer((Answer<String>) invocation ->
- "Signature:\n" + invocation.getArguments()[1] + "\n\n");
when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources");
when(mContext.getResources()).thenReturn(mResources);
when(mWifiDialogManager.createSimpleDialogWithUrl(
any(), any(), any(), anyInt(), anyInt(), any(), any(), any(), any(), any()))
.thenReturn(mTofuAlertDialog);
- when(mWifiDialogManager.createSimpleDialog(
- any(), any(), any(), any(), any(), any(), any()))
- .thenReturn(mTofuAlertDialog);
when(mFrameworkFacade.makeNotificationBuilder(any(), any()))
.thenReturn(mNotificationBuilder);
@@ -245,9 +207,6 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
assertTrue(mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected));
verify(mCallbacks).onError(eq(config.SSID));
- verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId),
- eq(WifiConfiguration.NetworkSelectionStatus
- .DISABLED_BY_WIFI_MANAGER));
}
/**
@@ -352,36 +311,9 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
isTrustOnFirstUseSupported, isUserSelected, needUserApproval);
}
- private X509Certificate generateMockCert(String subject, String issuer, boolean isCa) {
- X509Certificate mockCert = mock(X509Certificate.class);
- X500Principal mockSubjectPrincipal = mock(X500Principal.class);
- when(mockCert.getSubjectX500Principal()).thenReturn(mockSubjectPrincipal);
- when(mockSubjectPrincipal.getName()).thenReturn("C=TW,ST=Taiwan,L=Taipei"
- + ",O=" + subject + " Organization"
- + ",CN=" + subject
- + ",1.2.840.113549.1.9.1=#1614" + String.valueOf(HexEncoding.encode(
- (subject + "@email.com").getBytes(StandardCharsets.UTF_8))));
-
- X500Principal mockIssuerX500Principal = mock(X500Principal.class);
- when(mockCert.getIssuerX500Principal()).thenReturn(mockIssuerX500Principal);
- when(mockIssuerX500Principal.getName()).thenReturn("C=TW,ST=Taiwan,L=Taipei"
- + ",O=" + issuer + " Organization"
- + ",CN=" + issuer
- + ",1.2.840.113549.1.9.1=#1614" + String.valueOf(HexEncoding.encode(
- (issuer + "@email.com").getBytes(StandardCharsets.UTF_8))));
-
- when(mockCert.getSignature()).thenReturn(new byte[]{
- (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef,
- (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78,
- (byte) 0x90, (byte) 0xab, (byte) 0xcd, (byte) 0xef});
-
- when(mockCert.getBasicConstraints()).thenReturn(isCa ? 99 : -1);
- return mockCert;
- }
-
private WifiConfiguration prepareWifiConfiguration(boolean isAtLeastT) {
WifiConfiguration config = spy(WifiConfigurationTestUtil.createEapNetwork(
- WifiEnterpriseConfig.Eap.TTLS, WifiEnterpriseConfig.Phase2.MSCHAPV2));
+ WifiEnterpriseConfig.Eap.TLS, WifiEnterpriseConfig.Phase2.NONE));
config.networkId = FRAMEWORK_NETWORK_ID;
config.SSID = TEST_SSID;
if (isAtLeastT) {
@@ -389,8 +321,6 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
}
config.enterpriseConfig.setCaPath("");
config.enterpriseConfig.setDomainSuffixMatch("");
- config.enterpriseConfig.setIdentity(TEST_IDENTITY);
- config.enterpriseConfig.setPassword(TEST_PASSWORD);
return config;
}
@@ -408,32 +338,14 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
mWifiNative,
mFrameworkFacade,
mWifiNotificationManager,
- mWifiDialogManager,
- isTrustOnFirstUseSupported,
+ mWifiDialogManager, isTrustOnFirstUseSupported,
isInsecureEnterpriseConfigurationAllowed,
mCallbacks,
WIFI_IFACE_NAME,
mHandler);
- if (isTrustOnFirstUseSupported
- && (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS
- || config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP)
- && config.enterpriseConfig.getPhase2Method() != WifiEnterpriseConfig.Phase2.NONE) {
- // Verify that the configuration contains an identity
- assertEquals(TEST_IDENTITY, config.enterpriseConfig.getIdentity());
- assertEquals(TEST_PASSWORD, config.enterpriseConfig.getPassword());
- }
mInsecureEapNetworkHandler.prepareConnection(config);
- if (isTrustOnFirstUseSupported
- && (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS
- || config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP)
- && config.enterpriseConfig.getPhase2Method() != WifiEnterpriseConfig.Phase2.NONE) {
- // Verify identities are cleared
- assertTrue(TextUtils.isEmpty(config.enterpriseConfig.getIdentity()));
- assertTrue(TextUtils.isEmpty(config.enterpriseConfig.getPassword()));
- }
-
if (isTrustOnFirstUseSupported && config.enterpriseConfig.isTrustOnFirstUseEnabled()) {
verify(mContext, atLeastOnce()).registerReceiver(
mBroadcastReceiverCaptor.capture(),
@@ -467,13 +379,34 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
- X509Certificate mockCaCert = generateMockCert("ca", "ca", true);
- X509Certificate mockServerCert = generateMockCert("server", "ca", false);
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1, mockCaCert);
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockServerCert);
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 1, FakeKeys.CA_CERT0);
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 0, FakeKeys.CLIENT_CERT);
+
+ verifyTrustOnFirstUseFlow(config, ACTION_ACCEPT, isTrustOnFirstUseSupported,
+ isUserSelected, needUserApproval, FakeKeys.CA_CERT0, FakeKeys.CLIENT_CERT);
+ }
+
+ /**
+ * Verify Trust On First Use flow with a reversal cert chain
+ * - This network is selected by a user.
+ * - Accept the connection.
+ */
+ @Test
+ public void verifyTrustOnFirstUseAcceptWhenConnectByUserWithReversalOrderChain()
+ throws Exception {
+ assumeTrue(SdkLevel.isAtLeastT());
+ boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
+ boolean needUserApproval = true;
+
+ WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
+ setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
+
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 0, FakeKeys.CLIENT_CERT);
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 1, FakeKeys.CA_CERT1);
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 2, FakeKeys.CA_CERT0);
verifyTrustOnFirstUseFlow(config, ACTION_ACCEPT, isTrustOnFirstUseSupported,
- isUserSelected, needUserApproval, mockCaCert, mockServerCert);
+ isUserSelected, needUserApproval, FakeKeys.CA_CERT0, FakeKeys.CLIENT_CERT);
}
/**
@@ -491,11 +424,10 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
- X509Certificate mockSelfSignedCert = generateMockCert("self", "self", false);
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockSelfSignedCert);
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 0, FakeKeys.CA_CERT0);
verifyTrustOnFirstUseFlow(config, ACTION_ACCEPT, isTrustOnFirstUseSupported,
- isUserSelected, needUserApproval, mockSelfSignedCert, mockSelfSignedCert);
+ isUserSelected, needUserApproval, FakeKeys.CA_CERT0, FakeKeys.CA_CERT0);
}
/**
@@ -516,9 +448,6 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
assertEquals(needUserApproval,
mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected));
verify(mCallbacks).onError(eq(config.SSID));
- verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId),
- eq(WifiConfiguration.NetworkSelectionStatus
- .DISABLED_BY_WIFI_MANAGER));
}
/**
@@ -538,17 +467,11 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
config.enterpriseConfig.enableTrustOnFirstUse(false);
setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1,
- generateMockCert("ca", "ca", true));
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0,
- generateMockCert("server", "ca", false));
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 0, FakeKeys.CA_CERT0);
assertEquals(needUserApproval,
mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected));
verify(mCallbacks).onError(eq(config.SSID));
- verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId),
- eq(WifiConfiguration.NetworkSelectionStatus
- .DISABLED_BY_WIFI_MANAGER));
}
/**
@@ -556,161 +479,36 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
* - TOFU is supported.
* - Insecure EAP network is allowed.
* - TOFU is not enabled
- * - No user approval is needed.
*/
@Test
public void verifyNoErrorWithTofuDisabledWhenInsecureEapNetworkIsAllowed()
throws Exception {
assumeTrue(SdkLevel.isAtLeastT());
boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
- boolean needUserApproval = false, isInsecureEnterpriseConfigurationAllowed = true;
+ boolean needUserApproval = true, isInsecureEnterpriseConfigurationAllowed = true;
WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
config.enterpriseConfig.enableTrustOnFirstUse(false);
setupTest(config, isAtLeastT, isTrustOnFirstUseSupported,
isInsecureEnterpriseConfigurationAllowed);
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1,
- generateMockCert("ca", "ca", true));
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0,
- generateMockCert("server", "ca", false));
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 0, FakeKeys.CA_CERT0);
assertEquals(needUserApproval,
mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected));
verify(mCallbacks, never()).onError(any());
}
- /**
- * Verify that it reports errors if the cert chain is headless.
- */
- @Test
- public void verifyOnErrorWithHeadlessCertChain() throws Exception {
- assumeTrue(SdkLevel.isAtLeastT());
- boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
-
- WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
- setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
-
- // Missing root CA cert.
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0,
- generateMockCert("server", "ca", false));
-
- assertTrue(mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected));
- verify(mCallbacks).onError(eq(config.SSID));
- verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId),
- eq(WifiConfiguration.NetworkSelectionStatus
- .DISABLED_BY_WIFI_MANAGER));
- }
-
- /**
- * Verify that is reports errors if the server cert issuer does not match the parent subject.
- */
- @Test
- public void verifyOnErrorWithIncompleteChain() throws Exception {
- assumeTrue(SdkLevel.isAtLeastT());
- boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
-
- WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
- setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
-
- X509Certificate mockCaCert = generateMockCert("ca", "ca", true);
- // Missing intermediate cert.
- X509Certificate mockServerCert = generateMockCert("server", "intermediate", false);
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1, mockCaCert);
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockServerCert);
-
- assertTrue(mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected));
- verify(mCallbacks).onError(eq(config.SSID));
- verify(mWifiConfigManager, atLeastOnce()).updateNetworkSelectionStatus(eq(config.networkId),
- eq(WifiConfiguration.NetworkSelectionStatus
- .DISABLED_BY_WIFI_MANAGER));
- }
-
- /**
- * Verify that setting pending certificate won't crash with no current configuration.
- */
- @Test
- public void verifySetPendingCertificateNoCrashWithNoConfig()
- throws Exception {
- assumeTrue(SdkLevel.isAtLeastT());
- mInsecureEapNetworkHandler = new InsecureEapNetworkHandler(
- mContext,
- mWifiConfigManager,
- mWifiNative,
- mFrameworkFacade,
- mWifiNotificationManager,
- mWifiDialogManager,
- true /* isTrustOnFirstUseSupported */,
- false /* isInsecureEnterpriseConfigurationAllowed */,
- mCallbacks,
- WIFI_IFACE_NAME,
- mHandler);
- X509Certificate mockSelfSignedCert = generateMockCert("self", "self", false);
- mInsecureEapNetworkHandler.addPendingCertificate("NotExist", 0, mockSelfSignedCert);
- }
-
- @Test
- public void testExistingCertChainIsClearedOnPreparingNewConnection() throws Exception {
- assumeTrue(SdkLevel.isAtLeastT());
- boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
-
- WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
- setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
-
- // Missing root CA cert.
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0,
- generateMockCert("server", "ca", false));
-
- // The wrong cert chain should be cleared after this call.
- mInsecureEapNetworkHandler.prepareConnection(config);
-
- X509Certificate mockSelfSignedCert = generateMockCert("self", "self", false);
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockSelfSignedCert);
-
- assertTrue(mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected));
- verify(mCallbacks, never()).onError(any());
- }
-
- @Test
- public void verifyUserApprovalIsNotNeededWithDifferentTargetConfig() throws Exception {
- assumeTrue(SdkLevel.isAtLeastT());
- boolean isAtLeastT = true, isTrustOnFirstUseSupported = true, isUserSelected = true;
-
- WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
- setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
-
- X509Certificate mockSelfSignedCert = generateMockCert("self", "self", false);
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockSelfSignedCert);
-
- // Pass another PSK config which is not the same as the current one.
- WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork();
- pskConfig.networkId = FRAMEWORK_NETWORK_ID + 2;
- mInsecureEapNetworkHandler.prepareConnection(pskConfig);
- assertFalse(mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected));
- verify(mCallbacks, never()).onError(any());
-
- // Pass another non-TOFU EAP config which is not the same as the current one.
- WifiConfiguration anotherEapConfig = spy(WifiConfigurationTestUtil.createEapNetwork(
- WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
- anotherEapConfig.networkId = FRAMEWORK_NETWORK_ID + 1;
- mInsecureEapNetworkHandler.prepareConnection(anotherEapConfig);
- assertFalse(mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected));
- verify(mCallbacks, never()).onError(any());
- }
-
private void verifyTrustOnFirstUseFlowWithDefaultCerts(WifiConfiguration config,
int action, boolean isTrustOnFirstUseSupported, boolean isUserSelected,
boolean needUserApproval) throws Exception {
- X509Certificate mockCaCert = generateMockCert("ca", "ca", true);
- X509Certificate mockServerCert = generateMockCert("server", "middle", false);
if (isTrustOnFirstUseSupported) {
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 2, mockCaCert);
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 1,
- generateMockCert("middle", "ca", false));
- mInsecureEapNetworkHandler.addPendingCertificate(config.SSID, 0, mockServerCert);
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 2, FakeKeys.CA_CERT0);
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 1, FakeKeys.CA_CERT1);
+ mInsecureEapNetworkHandler.setPendingCertificate(config.SSID, 0, FakeKeys.CLIENT_CERT);
}
verifyTrustOnFirstUseFlow(config, action, isTrustOnFirstUseSupported,
- isUserSelected, needUserApproval, mockCaCert, mockServerCert);
+ isUserSelected, needUserApproval, FakeKeys.CA_CERT0, FakeKeys.CLIENT_CERT);
}
private void verifyTrustOnFirstUseFlow(WifiConfiguration config,
@@ -720,17 +518,12 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
assertEquals(needUserApproval,
mInsecureEapNetworkHandler.startUserApprovalIfNecessary(isUserSelected));
- ArgumentCaptor<String> dialogMessageCaptor = ArgumentCaptor.forClass(String.class);
if (isUserSelected) {
ArgumentCaptor<WifiDialogManager.SimpleDialogCallback> dialogCallbackCaptor =
ArgumentCaptor.forClass(WifiDialogManager.SimpleDialogCallback.class);
verify(mWifiDialogManager).createSimpleDialogWithUrl(
- any(), dialogMessageCaptor.capture(), any(), anyInt(), anyInt(), any(), any(),
- any(), dialogCallbackCaptor.capture(), any());
- if (isTrustOnFirstUseSupported) {
- assertTofuDialogMessage(expectedCaCert, expectedServerCert,
- dialogMessageCaptor.getValue());
- }
+ any(), any(), any(), anyInt(), anyInt(), any(), any(), any(),
+ dialogCallbackCaptor.capture(), any());
if (action == ACTION_ACCEPT) {
dialogCallbackCaptor.getValue().onPositiveButtonClicked();
} else if (action == ACTION_REJECT) {
@@ -740,7 +533,6 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
verify(mFrameworkFacade, never()).makeAlertDialogBuilder(any());
verify(mFrameworkFacade).makeNotificationBuilder(
eq(mContext), eq(WifiService.NOTIFICATION_NETWORK_ALERTS));
-
// Trust On First Use notification has no accept and reject action buttons.
// It only supports TAP and launch the dialog.
if (isTrustOnFirstUseSupported) {
@@ -751,10 +543,8 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
ArgumentCaptor<WifiDialogManager.SimpleDialogCallback> dialogCallbackCaptor =
ArgumentCaptor.forClass(WifiDialogManager.SimpleDialogCallback.class);
verify(mWifiDialogManager).createSimpleDialogWithUrl(
- any(), dialogMessageCaptor.capture(), any(), anyInt(), anyInt(), any(),
- any(), any(), dialogCallbackCaptor.capture(), any());
- assertTofuDialogMessage(expectedCaCert, expectedServerCert,
- dialogMessageCaptor.getValue());
+ any(), any(), any(), anyInt(), anyInt(), any(), any(), any(),
+ dialogCallbackCaptor.capture(), any());
if (action == ACTION_ACCEPT) {
dialogCallbackCaptor.getValue().onPositiveButtonClicked();
} else if (action == ACTION_REJECT) {
@@ -776,8 +566,7 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
}
if (action == ACTION_ACCEPT) {
- verify(mWifiConfigManager).updateNetworkSelectionStatus(eq(config.networkId),
- eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE));
+ verify(mWifiConfigManager).allowAutojoin(eq(config.networkId), eq(true));
if (isTrustOnFirstUseSupported) {
verify(mWifiConfigManager).updateCaCertificate(
eq(config.networkId), eq(expectedCaCert), eq(expectedServerCert));
@@ -787,10 +576,7 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
}
verify(mCallbacks).onAccept(eq(config.SSID));
} else if (action == ACTION_REJECT) {
- verify(mWifiConfigManager, atLeastOnce())
- .updateNetworkSelectionStatus(eq(config.networkId),
- eq(WifiConfiguration.NetworkSelectionStatus
- .DISABLED_BY_WIFI_MANAGER));
+ verify(mWifiConfigManager).allowAutojoin(eq(config.networkId), eq(false));
verify(mCallbacks).onReject(eq(config.SSID));
} else if (action == ACTION_TAP) {
verify(mWifiDialogManager).createSimpleDialogWithUrl(
@@ -800,44 +586,4 @@ public class InsecureEapNetworkHandlerTest extends WifiBaseTest {
verify(mCallbacks, never()).onError(any());
}
- private void assertTofuDialogMessage(
- X509Certificate rootCaCert,
- X509Certificate serverCert,
- String message) {
- CertificateSubjectInfo serverCertSubjectInfo =
- CertificateSubjectInfo.parse(serverCert.getSubjectX500Principal().getName());
- CertificateSubjectInfo serverCertIssuerInfo =
- CertificateSubjectInfo.parse(serverCert.getIssuerX500Principal().getName());
- assertNotNull("Server cert subject info is null", serverCertSubjectInfo);
- assertNotNull("Server cert issuer info is null", serverCertIssuerInfo);
-
- assertTrue("TOFU dialog message does not contain server cert subject name ",
- message.contains(serverCertSubjectInfo.commonName));
- assertTrue("TOFU dialog message does not contain server cert issuer name",
- message.contains(serverCertIssuerInfo.commonName));
- if (!TextUtils.isEmpty(serverCertSubjectInfo.organization)) {
- assertTrue("TOFU dialog message does not contain server cert organization",
- message.contains(serverCertSubjectInfo.organization));
- }
- if (!TextUtils.isEmpty(serverCertSubjectInfo.email)) {
- assertTrue("TOFU dialog message does not contain server cert email",
- message.contains(serverCertSubjectInfo.email));
- }
- assertTrue("TOFU dialog message does not contain server cert signature",
- message.contains(NativeUtil.hexStringFromByteArray(
- rootCaCert.getSignature()).substring(0, 16)));
- }
-
- @Test
- public void testCleanUp() throws Exception {
- assumeTrue(SdkLevel.isAtLeastT());
-
- boolean isAtLeastT = true, isTrustOnFirstUseSupported = true;
- WifiConfiguration config = prepareWifiConfiguration(isAtLeastT);
- setupTest(config, isAtLeastT, isTrustOnFirstUseSupported);
-
- BroadcastReceiver br = mBroadcastReceiverCaptor.getValue();
- mInsecureEapNetworkHandler.cleanup();
- verify(mContext).unregisterReceiver(br);
- }
}