Merge changes from topics "vpnmove-getconnectionowneruid", "vpnmove-systemdefaultcallback", "vpnmove-vpntransportinfo"

* changes:
  Stop using mVpns in getConnectionOwnerUid.
  Add a VpnTransportInfo object.
  Add a registerSystemDefaultNetworkCallback method.
This commit is contained in:
Lorenzo Colitti
2021-02-10 06:38:41 +00:00
committed by Gerrit Code Review
11 changed files with 324 additions and 69 deletions

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
import com.android.internal.util.MessageUtils;
import java.util.Objects;
/** @hide */
public final class VpnTransportInfo implements TransportInfo, Parcelable {
private static final SparseArray<String> sTypeToString =
MessageUtils.findMessageNames(new Class[]{VpnManager.class}, new String[]{"TYPE_VPN_"});
/** Type of this VPN. */
@VpnManager.VpnType public final int type;
public VpnTransportInfo(@VpnManager.VpnType int type) {
this.type = type;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof VpnTransportInfo)) return false;
VpnTransportInfo that = (VpnTransportInfo) o;
return this.type == that.type;
}
@Override
public int hashCode() {
return Objects.hash(type);
}
@Override
public String toString() {
final String typeString = sTypeToString.get(type, "VPN_TYPE_???");
return String.format("VpnTransportInfo{%s}", typeString);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(type);
}
public static final @NonNull Creator<VpnTransportInfo> CREATOR =
new Creator<VpnTransportInfo>() {
public VpnTransportInfo createFromParcel(Parcel in) {
return new VpnTransportInfo(in.readInt());
}
public VpnTransportInfo[] newArray(int size) {
return new VpnTransportInfo[size];
}
};
}

View File

@@ -21,6 +21,7 @@ import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
import static android.net.NetworkRequest.Type.LISTEN; import static android.net.NetworkRequest.Type.LISTEN;
import static android.net.NetworkRequest.Type.REQUEST; import static android.net.NetworkRequest.Type.REQUEST;
import static android.net.NetworkRequest.Type.TRACK_DEFAULT; import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT;
import static android.net.QosCallback.QosCallbackRegistrationException; import static android.net.QosCallback.QosCallbackRegistrationException;
import android.annotation.CallbackExecutor; import android.annotation.CallbackExecutor;
@@ -3721,7 +3722,8 @@ public class ConnectivityManager {
printStackTrace(); printStackTrace();
checkCallbackNotNull(callback); checkCallbackNotNull(callback);
Preconditions.checkArgument( Preconditions.checkArgument(
reqType == TRACK_DEFAULT || need != null, "null NetworkCapabilities"); reqType == TRACK_DEFAULT || reqType == TRACK_SYSTEM_DEFAULT || need != null,
"null NetworkCapabilities");
final NetworkRequest request; final NetworkRequest request;
final String callingPackageName = mContext.getOpPackageName(); final String callingPackageName = mContext.getOpPackageName();
try { try {
@@ -4192,8 +4194,9 @@ public class ConnectivityManager {
} }
/** /**
* Registers to receive notifications about changes in the system default network. The callbacks * Registers to receive notifications about changes in the application's default network. This
* will continue to be called until either the application exits or * may be a physical network or a virtual network, such as a VPN that applies to the
* application. The callbacks will continue to be called until either the application exits or
* {@link #unregisterNetworkCallback(NetworkCallback)} is called. * {@link #unregisterNetworkCallback(NetworkCallback)} is called.
* *
* <p>To avoid performance issues due to apps leaking callbacks, the system will limit the * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the
@@ -4206,7 +4209,7 @@ public class ConnectivityManager {
* {@link #unregisterNetworkCallback(NetworkCallback)}. * {@link #unregisterNetworkCallback(NetworkCallback)}.
* *
* @param networkCallback The {@link NetworkCallback} that the system will call as the * @param networkCallback The {@link NetworkCallback} that the system will call as the
* system default network changes. * application's default network changes.
* The callback is invoked on the default internal Handler. * The callback is invoked on the default internal Handler.
* @throws RuntimeException if the app already has too many callbacks registered. * @throws RuntimeException if the app already has too many callbacks registered.
*/ */
@@ -4215,11 +4218,47 @@ public class ConnectivityManager {
registerDefaultNetworkCallback(networkCallback, getDefaultHandler()); registerDefaultNetworkCallback(networkCallback, getDefaultHandler());
} }
/**
* Registers to receive notifications about changes in the application's default network. This
* may be a physical network or a virtual network, such as a VPN that applies to the
* application. The callbacks will continue to be called until either the application exits or
* {@link #unregisterNetworkCallback(NetworkCallback)} is called.
*
* <p>To avoid performance issues due to apps leaking callbacks, the system will limit the
* number of outstanding requests to 100 per app (identified by their UID), shared with
* all variants of this method, of {@link #requestNetwork} as well as
* {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}.
* Requesting a network with this method will count toward this limit. If this limit is
* exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources,
* make sure to unregister the callbacks with
* {@link #unregisterNetworkCallback(NetworkCallback)}.
*
* @param networkCallback The {@link NetworkCallback} that the system will call as the
* application's default network changes.
* @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
* @throws RuntimeException if the app already has too many callbacks registered.
*/
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback,
@NonNull Handler handler) {
CallbackHandler cbHandler = new CallbackHandler(handler);
sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0,
TRACK_DEFAULT, TYPE_NONE, cbHandler);
}
/** /**
* Registers to receive notifications about changes in the system default network. The callbacks * Registers to receive notifications about changes in the system default network. The callbacks
* will continue to be called until either the application exits or * will continue to be called until either the application exits or
* {@link #unregisterNetworkCallback(NetworkCallback)} is called. * {@link #unregisterNetworkCallback(NetworkCallback)} is called.
* *
* This method should not be used to determine networking state seen by applications, because in
* many cases, most or even all application traffic may not use the default network directly,
* and traffic from different applications may go on different networks by default. As an
* example, if a VPN is connected, traffic from all applications might be sent through the VPN
* and not onto the system default network. Applications or system components desiring to do
* determine network state as seen by applications should use other methods such as
* {@link #registerDefaultNetworkCallback(NetworkCallback, Handler)}.
*
* <p>To avoid performance issues due to apps leaking callbacks, the system will limit the * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the
* number of outstanding requests to 100 per app (identified by their UID), shared with * number of outstanding requests to 100 per app (identified by their UID), shared with
* all variants of this method, of {@link #requestNetwork} as well as * all variants of this method, of {@link #requestNetwork} as well as
@@ -4233,20 +4272,19 @@ public class ConnectivityManager {
* system default network changes. * system default network changes.
* @param handler {@link Handler} to specify the thread upon which the callback will be invoked. * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
* @throws RuntimeException if the app already has too many callbacks registered. * @throws RuntimeException if the app already has too many callbacks registered.
*
* @hide
*/ */
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @SystemApi(client = MODULE_LIBRARIES)
public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, @SuppressLint({"ExecutorRegistration", "PairedRegistration"})
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_SETTINGS})
public void registerSystemDefaultNetworkCallback(@NonNull NetworkCallback networkCallback,
@NonNull Handler handler) { @NonNull Handler handler) {
// This works because if the NetworkCapabilities are null,
// ConnectivityService takes them from the default request.
//
// Since the capabilities are exactly the same as the default request's
// capabilities, this request is guaranteed, at all times, to be
// satisfied by the same network, if any, that satisfies the default
// request, i.e., the system default network.
CallbackHandler cbHandler = new CallbackHandler(handler); CallbackHandler cbHandler = new CallbackHandler(handler);
sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0, sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0,
TRACK_DEFAULT, TYPE_NONE, cbHandler); TRACK_SYSTEM_DEFAULT, TYPE_NONE, cbHandler);
} }
/** /**

View File

@@ -762,12 +762,14 @@ public final class NetworkCapabilities implements Parcelable {
final int originalSignalStrength = mSignalStrength; final int originalSignalStrength = mSignalStrength;
final int originalOwnerUid = getOwnerUid(); final int originalOwnerUid = getOwnerUid();
final int[] originalAdministratorUids = getAdministratorUids(); final int[] originalAdministratorUids = getAdministratorUids();
final TransportInfo originalTransportInfo = getTransportInfo();
clearAll(); clearAll();
mTransportTypes = (originalTransportTypes & TEST_NETWORKS_ALLOWED_TRANSPORTS) mTransportTypes = (originalTransportTypes & TEST_NETWORKS_ALLOWED_TRANSPORTS)
| (1 << TRANSPORT_TEST); | (1 << TRANSPORT_TEST);
mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES;
mNetworkSpecifier = originalSpecifier; mNetworkSpecifier = originalSpecifier;
mSignalStrength = originalSignalStrength; mSignalStrength = originalSignalStrength;
mTransportInfo = originalTransportInfo;
// Only retain the owner and administrator UIDs if they match the app registering the remote // Only retain the owner and administrator UIDs if they match the app registering the remote
// caller that registered the network. // caller that registered the network.

View File

@@ -104,17 +104,14 @@ public class NetworkRequest implements Parcelable {
* callbacks about the single, highest scoring current network * callbacks about the single, highest scoring current network
* (if any) that matches the specified NetworkCapabilities, or * (if any) that matches the specified NetworkCapabilities, or
* *
* - TRACK_DEFAULT, a hybrid of the two designed such that the * - TRACK_DEFAULT, which causes the framework to issue callbacks for
* framework will issue callbacks for the single, highest scoring * the single, highest scoring current network (if any) that will
* current network (if any) that matches the capabilities of the * be chosen for an app, but which cannot cause the framework to
* default Internet request (mDefaultRequest), but which cannot cause * either create or retain the existence of any specific network.
* the framework to either create or retain the existence of any *
* specific network. Note that from the point of view of the request * - TRACK_SYSTEM_DEFAULT, which causes the framework to send callbacks
* matching code, TRACK_DEFAULT is identical to REQUEST: its special * for the network (if any) that satisfies the default Internet
* behaviour is not due to different semantics, but to the fact that * request.
* the system will only ever create a TRACK_DEFAULT with capabilities
* that are identical to the default request's capabilities, thus
* causing it to share fate in every way with the default request.
* *
* - BACKGROUND_REQUEST, like REQUEST but does not cause any networks * - BACKGROUND_REQUEST, like REQUEST but does not cause any networks
* to retain the NET_CAPABILITY_FOREGROUND capability. A network with * to retain the NET_CAPABILITY_FOREGROUND capability. A network with
@@ -137,6 +134,7 @@ public class NetworkRequest implements Parcelable {
TRACK_DEFAULT, TRACK_DEFAULT,
REQUEST, REQUEST,
BACKGROUND_REQUEST, BACKGROUND_REQUEST,
TRACK_SYSTEM_DEFAULT,
}; };
/** /**
@@ -601,6 +599,8 @@ public class NetworkRequest implements Parcelable {
return NetworkRequestProto.TYPE_REQUEST; return NetworkRequestProto.TYPE_REQUEST;
case BACKGROUND_REQUEST: case BACKGROUND_REQUEST:
return NetworkRequestProto.TYPE_BACKGROUND_REQUEST; return NetworkRequestProto.TYPE_BACKGROUND_REQUEST;
case TRACK_SYSTEM_DEFAULT:
return NetworkRequestProto.TYPE_TRACK_SYSTEM_DEFAULT;
default: default:
return NetworkRequestProto.TYPE_UNKNOWN; return NetworkRequestProto.TYPE_UNKNOWN;
} }

View File

@@ -55,13 +55,29 @@ import java.security.GeneralSecurityException;
public class VpnManager { public class VpnManager {
/** Type representing a lack of VPN @hide */ /** Type representing a lack of VPN @hide */
public static final int TYPE_VPN_NONE = -1; public static final int TYPE_VPN_NONE = -1;
/** VPN service type code @hide */
/**
* A VPN created by an app using the {@link VpnService} API.
* @hide
*/
public static final int TYPE_VPN_SERVICE = 1; public static final int TYPE_VPN_SERVICE = 1;
/** Platform VPN type code @hide */
/**
* A VPN created using a {@link VpnManager} API such as {@link #startProvisionedVpnProfile}.
* @hide
*/
public static final int TYPE_VPN_PLATFORM = 2; public static final int TYPE_VPN_PLATFORM = 2;
/**
* An IPsec VPN created by the built-in LegacyVpnRunner.
* @deprecated new Android devices should use VPN_TYPE_PLATFORM instead.
* @hide
*/
@Deprecated
public static final int TYPE_VPN_LEGACY = 3;
/** @hide */ /** @hide */
@IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM}) @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
public @interface VpnType {} public @interface VpnType {}

View File

@@ -132,12 +132,14 @@ import android.net.RouteInfo;
import android.net.RouteInfoParcel; import android.net.RouteInfoParcel;
import android.net.SocketKeepalive; import android.net.SocketKeepalive;
import android.net.TetheringManager; import android.net.TetheringManager;
import android.net.TransportInfo;
import android.net.UidRange; import android.net.UidRange;
import android.net.UidRangeParcel; import android.net.UidRangeParcel;
import android.net.UnderlyingNetworkInfo; import android.net.UnderlyingNetworkInfo;
import android.net.Uri; import android.net.Uri;
import android.net.VpnManager; import android.net.VpnManager;
import android.net.VpnService; import android.net.VpnService;
import android.net.VpnTransportInfo;
import android.net.metrics.INetdEventListener; import android.net.metrics.INetdEventListener;
import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent; import android.net.metrics.NetworkEvent;
@@ -5747,6 +5749,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
throw new SecurityException("Insufficient permissions to specify legacy type"); throw new SecurityException("Insufficient permissions to specify legacy type");
} }
} }
final NetworkCapabilities defaultNc = mDefaultRequest.mRequests.get(0).networkCapabilities;
final int callingUid = mDeps.getCallingUid(); final int callingUid = mDeps.getCallingUid();
final NetworkRequest.Type reqType; final NetworkRequest.Type reqType;
try { try {
@@ -5757,11 +5760,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
switch (reqType) { switch (reqType) {
case TRACK_DEFAULT: case TRACK_DEFAULT:
// If the request type is TRACK_DEFAULT, the passed {@code networkCapabilities} // If the request type is TRACK_DEFAULT, the passed {@code networkCapabilities}
// is unused and will be replaced by the one from the default network request. // is unused and will be replaced by ones appropriate for the caller.
// This allows callers to keep track of the system default network. // This allows callers to keep track of the default network for their app.
networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid); networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid);
enforceAccessPermission(); enforceAccessPermission();
break; break;
case TRACK_SYSTEM_DEFAULT:
enforceSettingsPermission();
networkCapabilities = new NetworkCapabilities(defaultNc);
break;
case BACKGROUND_REQUEST: case BACKGROUND_REQUEST:
enforceNetworkStackOrSettingsPermission(); enforceNetworkStackOrSettingsPermission();
// Fall-through since other checks are the same with normal requests. // Fall-through since other checks are the same with normal requests.
@@ -5780,6 +5787,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
ensureRequestableCapabilities(networkCapabilities); ensureRequestableCapabilities(networkCapabilities);
ensureSufficientPermissionsForRequest(networkCapabilities, ensureSufficientPermissionsForRequest(networkCapabilities,
Binder.getCallingPid(), callingUid, callingPackageName); Binder.getCallingPid(), callingUid, callingPackageName);
// Set the UID range for this request to the single UID of the requester, or to an empty // Set the UID range for this request to the single UID of the requester, or to an empty
// set of UIDs if the caller has the appropriate permission and UIDs have not been set. // set of UIDs if the caller has the appropriate permission and UIDs have not been set.
// This will overwrite any allowed UIDs in the requested capabilities. Though there // This will overwrite any allowed UIDs in the requested capabilities. Though there
@@ -5799,6 +5807,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
new NetworkRequestInfo(messenger, networkRequest, binder, callingAttributionTag); new NetworkRequestInfo(messenger, networkRequest, binder, callingAttributionTag);
if (DBG) log("requestNetwork for " + nri); if (DBG) log("requestNetwork for " + nri);
// For TRACK_SYSTEM_DEFAULT callbacks, the capabilities have been modified since they were
// copied from the default request above. (This is necessary to ensure, for example, that
// the callback does not leak sensitive information to unprivileged apps.) Check that the
// changes don't alter request matching.
if (reqType == NetworkRequest.Type.TRACK_SYSTEM_DEFAULT &&
(!networkCapabilities.equalRequestableCapabilities(defaultNc))) {
Log.wtf(TAG, "TRACK_SYSTEM_DEFAULT capabilities don't match default request: "
+ networkCapabilities + " vs. " + defaultNc);
}
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri)); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
if (timeoutMs > 0) { if (timeoutMs > 0) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST, mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
@@ -8462,22 +8480,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
} }
/** private @VpnManager.VpnType int getVpnType(@Nullable NetworkAgentInfo vpn) {
* Caller either needs to be an active VPN, or hold the NETWORK_STACK permission if (vpn == null) return VpnManager.TYPE_VPN_NONE;
* for testing. final TransportInfo ti = vpn.networkCapabilities.getTransportInfo();
*/ if (!(ti instanceof VpnTransportInfo)) return VpnManager.TYPE_VPN_NONE;
private Vpn enforceActiveVpnOrNetworkStackPermission() { return ((VpnTransportInfo) ti).type;
if (checkNetworkStackPermission()) {
return null;
}
synchronized (mVpns) {
Vpn vpn = getVpnIfOwner();
if (vpn != null) {
return vpn;
}
}
throw new SecurityException("App must either be an active VPN or have the NETWORK_STACK "
+ "permission");
} }
/** /**
@@ -8487,14 +8494,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
* connection is not found. * connection is not found.
*/ */
public int getConnectionOwnerUid(ConnectionInfo connectionInfo) { public int getConnectionOwnerUid(ConnectionInfo connectionInfo) {
final Vpn vpn = enforceActiveVpnOrNetworkStackPermission();
// Only VpnService based VPNs should be able to get this information.
if (vpn != null && vpn.getActiveAppVpnType() != VpnManager.TYPE_VPN_SERVICE) {
throw new SecurityException(
"getConnectionOwnerUid() not allowed for non-VpnService VPNs");
}
if (connectionInfo.protocol != IPPROTO_TCP && connectionInfo.protocol != IPPROTO_UDP) { if (connectionInfo.protocol != IPPROTO_TCP && connectionInfo.protocol != IPPROTO_UDP) {
throw new IllegalArgumentException("Unsupported protocol " + connectionInfo.protocol); throw new IllegalArgumentException("Unsupported protocol " + connectionInfo.protocol);
} }
@@ -8502,8 +8501,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
final int uid = mDeps.getConnectionOwnerUid(connectionInfo.protocol, final int uid = mDeps.getConnectionOwnerUid(connectionInfo.protocol,
connectionInfo.local, connectionInfo.remote); connectionInfo.local, connectionInfo.remote);
/* Filter out Uids not associated with the VPN. */ if (uid == INVALID_UID) return uid; // Not found.
if (vpn != null && !vpn.appliesToUid(uid)) {
// Connection owner UIDs are visible only to the network stack and to the VpnService-based
// VPN, if any, that applies to the UID that owns the connection.
if (checkNetworkStackPermission()) return uid;
final NetworkAgentInfo vpn = getVpnForUid(uid);
if (vpn == null || getVpnType(vpn) != VpnManager.TYPE_VPN_SERVICE
|| vpn.networkCapabilities.getOwnerUid() != Binder.getCallingUid()) {
return INVALID_UID; return INVALID_UID;
} }

View File

@@ -717,8 +717,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
mNumBackgroundNetworkRequests += delta; mNumBackgroundNetworkRequests += delta;
break; break;
case TRACK_DEFAULT:
case LISTEN: case LISTEN:
case TRACK_DEFAULT:
case TRACK_SYSTEM_DEFAULT:
break; break;
case NONE: case NONE:

View File

@@ -35,6 +35,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
import static android.net.NetworkRequest.Type.REQUEST; import static android.net.NetworkRequest.Type.REQUEST;
import static android.net.NetworkRequest.Type.TRACK_DEFAULT; import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@@ -329,6 +330,9 @@ public class ConnectivityManagerTest {
mustFail(() -> { manager.registerDefaultNetworkCallback(null, handler); }); mustFail(() -> { manager.registerDefaultNetworkCallback(null, handler); });
mustFail(() -> { manager.registerDefaultNetworkCallback(callback, null); }); mustFail(() -> { manager.registerDefaultNetworkCallback(callback, null); });
mustFail(() -> { manager.registerSystemDefaultNetworkCallback(null, handler); });
mustFail(() -> { manager.registerSystemDefaultNetworkCallback(callback, null); });
mustFail(() -> { manager.unregisterNetworkCallback(nullCallback); }); mustFail(() -> { manager.unregisterNetworkCallback(nullCallback); });
mustFail(() -> { manager.unregisterNetworkCallback(nullIntent); }); mustFail(() -> { manager.unregisterNetworkCallback(nullIntent); });
mustFail(() -> { manager.releaseNetworkRequest(nullIntent); }); mustFail(() -> { manager.releaseNetworkRequest(nullIntent); });
@@ -377,6 +381,13 @@ public class ConnectivityManagerTest {
eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE),
eq(testPkgName), eq(testAttributionTag)); eq(testPkgName), eq(testAttributionTag));
reset(mService); reset(mService);
Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
manager.registerSystemDefaultNetworkCallback(callback, handler);
verify(mService).requestNetwork(eq(null),
eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE),
eq(testPkgName), eq(testAttributionTag));
reset(mService);
} }
static Message makeMessage(NetworkRequest req, int messageType) { static Message makeMessage(NetworkRequest req, int messageType) {

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net;
import static com.android.testutils.ParcelUtils.assertParcelSane;
import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VpnTransportInfoTest {
@Test
public void testParceling() {
VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
assertParcelSane(v, 1 /* fieldCount */);
assertParcelingIsLossless(v);
}
@Test
public void testEqualsAndHashCode() {
VpnTransportInfo v1 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
VpnTransportInfo v2 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE);
VpnTransportInfo v3 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
assertNotEquals(v1, v2);
assertEquals(v1, v3);
assertEquals(v1.hashCode(), v3.hashCode());
}
}

View File

@@ -205,6 +205,7 @@ import android.net.UidRangeParcel;
import android.net.UnderlyingNetworkInfo; import android.net.UnderlyingNetworkInfo;
import android.net.Uri; import android.net.Uri;
import android.net.VpnManager; import android.net.VpnManager;
import android.net.VpnTransportInfo;
import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpConnectivityLog;
import android.net.shared.NetworkMonitorUtils; import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig; import android.net.shared.PrivateDnsConfig;
@@ -1110,7 +1111,7 @@ public class ConnectivityServiceTest {
} }
@Override @Override
public int getActiveAppVpnType() { public int getActiveVpnType() {
return mVpnType; return mVpnType;
} }
@@ -1123,10 +1124,12 @@ public class ConnectivityServiceTest {
private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp) private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
throws Exception { throws Exception {
if (mAgentRegistered) throw new IllegalStateException("already registered"); if (mAgentRegistered) throw new IllegalStateException("already registered");
updateState(NetworkInfo.DetailedState.CONNECTING, "registerAgent");
mConfig = new VpnConfig(); mConfig = new VpnConfig();
setUids(uids); setUids(uids);
if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED); if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
mInterface = VPN_IFNAME; mInterface = VPN_IFNAME;
mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp, mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
mNetworkCapabilities); mNetworkCapabilities);
mMockNetworkAgent.waitForIdle(TIMEOUT_MS); mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
@@ -3649,10 +3652,19 @@ public class ConnectivityServiceTest {
@Test @Test
public void testRegisterDefaultNetworkCallback() throws Exception { public void testRegisterDefaultNetworkCallback() throws Exception {
// NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback.
mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
PERMISSION_GRANTED);
final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultNetworkCallback); mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
defaultNetworkCallback.assertNoCallback(); defaultNetworkCallback.assertNoCallback();
final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, handler);
systemDefaultCallback.assertNoCallback();
// Create a TRANSPORT_CELLULAR request to keep the mobile interface up // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
// whenever Wi-Fi is up. Without this, the mobile network agent is // whenever Wi-Fi is up. Without this, the mobile network agent is
// reaped before any other activity can take place. // reaped before any other activity can take place.
@@ -3667,27 +3679,35 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.connect(true); mCellNetworkAgent.connect(true);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
systemDefaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring up wifi and expect CALLBACK_AVAILABLE. // Bring up wifi and expect CALLBACK_AVAILABLE.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true); mWiFiNetworkAgent.connect(true);
cellNetworkCallback.assertNoCallback(); cellNetworkCallback.assertNoCallback();
defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
systemDefaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring down cell. Expect no default network callback, since it wasn't the default. // Bring down cell. Expect no default network callback, since it wasn't the default.
mCellNetworkAgent.disconnect(); mCellNetworkAgent.disconnect();
cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
defaultNetworkCallback.assertNoCallback(); defaultNetworkCallback.assertNoCallback();
systemDefaultCallback.assertNoCallback();
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring up cell. Expect no default network callback, since it won't be the default. // Bring up cell. Expect no default network callback, since it won't be the default.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true); mCellNetworkAgent.connect(true);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultNetworkCallback.assertNoCallback(); defaultNetworkCallback.assertNoCallback();
systemDefaultCallback.assertNoCallback();
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Bring down wifi. Expect the default network callback to notified of LOST wifi // Bring down wifi. Expect the default network callback to notified of LOST wifi
// followed by AVAILABLE cell. // followed by AVAILABLE cell.
@@ -3695,19 +3715,25 @@ public class ConnectivityServiceTest {
cellNetworkCallback.assertNoCallback(); cellNetworkCallback.assertNoCallback();
defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
systemDefaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
mCellNetworkAgent.disconnect(); mCellNetworkAgent.disconnect();
cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
systemDefaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
waitForIdle(); waitForIdle();
assertEquals(null, mCm.getActiveNetwork()); assertEquals(null, mCm.getActiveNetwork());
mMockVpn.establishForMyUid(); mMockVpn.establishForMyUid();
assertUidRangesUpdatedForMyUid(true); assertUidRangesUpdatedForMyUid(true);
defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
systemDefaultCallback.assertNoCallback();
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
assertEquals(null, systemDefaultCallback.getLastAvailableNetwork());
mMockVpn.disconnect(); mMockVpn.disconnect();
defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn); defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
systemDefaultCallback.assertNoCallback();
waitForIdle(); waitForIdle();
assertEquals(null, mCm.getActiveNetwork()); assertEquals(null, mCm.getActiveNetwork());
} }
@@ -6134,6 +6160,10 @@ public class ConnectivityServiceTest {
@Test @Test
public void testVpnNetworkActive() throws Exception { public void testVpnNetworkActive() throws Exception {
// NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback.
mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
PERMISSION_GRANTED);
final int uid = Process.myUid(); final int uid = Process.myUid();
final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
@@ -6141,6 +6171,7 @@ public class ConnectivityServiceTest {
final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
final TestNetworkCallback defaultCallback = new TestNetworkCallback(); final TestNetworkCallback defaultCallback = new TestNetworkCallback();
final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build(); final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
final NetworkRequest genericRequest = new NetworkRequest.Builder() final NetworkRequest genericRequest = new NetworkRequest.Builder()
.removeCapability(NET_CAPABILITY_NOT_VPN).build(); .removeCapability(NET_CAPABILITY_NOT_VPN).build();
@@ -6154,6 +6185,8 @@ public class ConnectivityServiceTest {
mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
mCm.registerDefaultNetworkCallback(defaultCallback); mCm.registerDefaultNetworkCallback(defaultCallback);
mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
new Handler(ConnectivityThread.getInstanceLooper()));
defaultCallback.assertNoCallback(); defaultCallback.assertNoCallback();
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
@@ -6163,6 +6196,7 @@ public class ConnectivityServiceTest {
genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
vpnNetworkCallback.assertNoCallback(); vpnNetworkCallback.assertNoCallback();
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -6183,7 +6217,10 @@ public class ConnectivityServiceTest {
wifiNetworkCallback.assertNoCallback(); wifiNetworkCallback.assertNoCallback();
vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
systemDefaultCallback.assertNoCallback();
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
assertEquals(mWiFiNetworkAgent.getNetwork(),
systemDefaultCallback.getLastAvailableNetwork());
ranges.clear(); ranges.clear();
mMockVpn.setUids(ranges); mMockVpn.setUids(ranges);
@@ -6200,6 +6237,7 @@ public class ConnectivityServiceTest {
// much, but that is the reason the test here has to check for an update to the // much, but that is the reason the test here has to check for an update to the
// capabilities instead of the expected LOST then AVAILABLE. // capabilities instead of the expected LOST then AVAILABLE.
defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn); defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
systemDefaultCallback.assertNoCallback();
ranges.add(new UidRange(uid, uid)); ranges.add(new UidRange(uid, uid));
mMockVpn.setUids(ranges); mMockVpn.setUids(ranges);
@@ -6211,6 +6249,7 @@ public class ConnectivityServiceTest {
// TODO : Here like above, AVAILABLE would be correct, but because this can't actually // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
// happen outside of the test, ConnectivityService does not rematch callbacks. // happen outside of the test, ConnectivityService does not rematch callbacks.
defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn); defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
systemDefaultCallback.assertNoCallback();
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
@@ -6219,6 +6258,7 @@ public class ConnectivityServiceTest {
wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
vpnNetworkCallback.assertNoCallback(); vpnNetworkCallback.assertNoCallback();
defaultCallback.assertNoCallback(); defaultCallback.assertNoCallback();
systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
mMockVpn.disconnect(); mMockVpn.disconnect();
@@ -6227,12 +6267,14 @@ public class ConnectivityServiceTest {
wifiNetworkCallback.assertNoCallback(); wifiNetworkCallback.assertNoCallback();
vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn); vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn); defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
systemDefaultCallback.assertNoCallback();
assertEquals(null, mCm.getActiveNetwork()); assertEquals(null, mCm.getActiveNetwork());
mCm.unregisterNetworkCallback(genericNetworkCallback); mCm.unregisterNetworkCallback(genericNetworkCallback);
mCm.unregisterNetworkCallback(wifiNetworkCallback); mCm.unregisterNetworkCallback(wifiNetworkCallback);
mCm.unregisterNetworkCallback(vpnNetworkCallback); mCm.unregisterNetworkCallback(vpnNetworkCallback);
mCm.unregisterNetworkCallback(defaultCallback); mCm.unregisterNetworkCallback(defaultCallback);
mCm.unregisterNetworkCallback(systemDefaultCallback);
} }
@Test @Test
@@ -7283,6 +7325,7 @@ public class ConnectivityServiceTest {
} }
private void establishLegacyLockdownVpn() throws Exception { private void establishLegacyLockdownVpn() throws Exception {
mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
// The legacy lockdown VPN only supports userId 0. // The legacy lockdown VPN only supports userId 0.
final Set<UidRange> ranges = Collections.singleton(UidRange.createForUser(PRIMARY_USER)); final Set<UidRange> ranges = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
mMockVpn.registerAgent(ranges); mMockVpn.registerAgent(ranges);
@@ -7395,6 +7438,9 @@ public class ConnectivityServiceTest {
assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR)); assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR));
assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI)); assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI));
assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
VpnTransportInfo ti = (VpnTransportInfo) vpnNc.getTransportInfo();
assertNotNull(ti);
assertEquals(VpnManager.TYPE_VPN_LEGACY, ti.type);
// Switch default network from cell to wifi. Expect VPN to disconnect and reconnect. // Switch default network from cell to wifi. Expect VPN to disconnect and reconnect.
final LinkProperties wifiLp = new LinkProperties(); final LinkProperties wifiLp = new LinkProperties();
@@ -8521,11 +8567,7 @@ public class ConnectivityServiceTest {
final int myUid = Process.myUid(); final int myUid = Process.myUid();
setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM); setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
try { assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
mService.getConnectionOwnerUid(getTestConnectionInfo());
fail("Expected SecurityException for non-VpnService app");
} catch (SecurityException expected) {
}
} }
@Test @Test
@@ -8533,11 +8575,7 @@ public class ConnectivityServiceTest {
final int myUid = Process.myUid(); final int myUid = Process.myUid();
setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE); setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
try { assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
mService.getConnectionOwnerUid(getTestConnectionInfo());
fail("Expected SecurityException for non-VpnService app");
} catch (SecurityException expected) {
}
} }
@Test @Test

View File

@@ -25,6 +25,7 @@ import static android.net.ConnectivityManager.NetworkCallback;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@@ -74,6 +75,7 @@ import android.net.UidRange;
import android.net.UidRangeParcel; import android.net.UidRangeParcel;
import android.net.VpnManager; import android.net.VpnManager;
import android.net.VpnService; import android.net.VpnService;
import android.net.VpnTransportInfo;
import android.net.ipsec.ike.IkeSessionCallback; import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.exceptions.IkeProtocolException; import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.os.Build.VERSION_CODES; import android.os.Build.VERSION_CODES;
@@ -984,6 +986,13 @@ public class VpnTest {
startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve
} }
private void assertTransportInfoMatches(NetworkCapabilities nc, int type) {
assertNotNull(nc);
VpnTransportInfo ti = (VpnTransportInfo) nc.getTransportInfo();
assertNotNull(ti);
assertEquals(type, ti.type);
}
public void startRacoon(final String serverAddr, final String expectedAddr) public void startRacoon(final String serverAddr, final String expectedAddr)
throws Exception { throws Exception {
final ConditionVariable legacyRunnerReady = new ConditionVariable(); final ConditionVariable legacyRunnerReady = new ConditionVariable();
@@ -1020,8 +1029,10 @@ public class VpnTest {
// Now wait for the runner to be ready before testing for the route. // Now wait for the runner to be ready before testing for the route.
ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class); ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class);
ArgumentCaptor<NetworkCapabilities> ncCaptor =
ArgumentCaptor.forClass(NetworkCapabilities.class);
verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(), verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(),
lpCaptor.capture(), any(), anyInt(), any(), anyInt()); lpCaptor.capture(), ncCaptor.capture(), anyInt(), any(), anyInt());
// In this test the expected address is always v4 so /32. // In this test the expected address is always v4 so /32.
// Note that the interface needs to be specified because RouteInfo objects stored in // Note that the interface needs to be specified because RouteInfo objects stored in
@@ -1031,6 +1042,8 @@ public class VpnTest {
final List<RouteInfo> actualRoutes = lpCaptor.getValue().getRoutes(); final List<RouteInfo> actualRoutes = lpCaptor.getValue().getRoutes();
assertTrue("Expected throw route (" + expectedRoute + ") not found in " + actualRoutes, assertTrue("Expected throw route (" + expectedRoute + ") not found in " + actualRoutes,
actualRoutes.contains(expectedRoute)); actualRoutes.contains(expectedRoute));
assertTransportInfoMatches(ncCaptor.getValue(), VpnManager.TYPE_VPN_LEGACY);
} finally { } finally {
// Now interrupt the thread, unblock the runner and clean up. // Now interrupt the thread, unblock the runner and clean up.
vpn.mVpnRunner.exitVpnRunner(); vpn.mVpnRunner.exitVpnRunner();