Merge "Add Network security watchlist service"

This commit is contained in:
Hugo Benichi
2017-11-12 22:24:56 +00:00
committed by Gerrit Code Review
6 changed files with 70 additions and 24 deletions

View File

@@ -30,11 +30,11 @@ interface IIpConnectivityMetrics {
int logEvent(in ConnectivityMetricsEvent event); int logEvent(in ConnectivityMetricsEvent event);
/** /**
* At most one callback can be registered (by DevicePolicyManager). * Callback can be registered by DevicePolicyManager or NetworkWatchlistService only.
* @return status {@code true} if registering/unregistering of the callback was successful, * @return status {@code true} if registering/unregistering of the callback was successful,
* {@code false} otherwise (might happen if IIpConnectivityMetrics is not available, * {@code false} otherwise (might happen if IIpConnectivityMetrics is not available,
* if it happens make sure you call it when the service is up in the caller) * if it happens make sure you call it when the service is up in the caller)
*/ */
boolean registerNetdEventCallback(in INetdEventCallback callback); boolean addNetdEventCallback(in int callerType, in INetdEventCallback callback);
boolean unregisterNetdEventCallback(); boolean removeNetdEventCallback(in int callerType);
} }

View File

@@ -19,6 +19,10 @@ package android.net;
/** {@hide} */ /** {@hide} */
oneway interface INetdEventCallback { oneway interface INetdEventCallback {
// Possible addNetdEventCallback callers.
const int CALLBACK_CALLER_DEVICE_POLICY = 0;
const int CALLBACK_CALLER_NETWORK_WATCHLIST = 1;
/** /**
* Reports a single DNS lookup function call. * Reports a single DNS lookup function call.
* This method must not block or perform long-running operations. * This method must not block or perform long-running operations.

View File

@@ -23,8 +23,6 @@ import android.net.INetdEventCallback;
import android.net.metrics.ApfProgramEvent; import android.net.metrics.ApfProgramEvent;
import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpConnectivityLog;
import android.os.Binder; import android.os.Binder;
import android.os.IBinder;
import android.os.Parcelable;
import android.os.Process; import android.os.Process;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
@@ -322,22 +320,22 @@ final public class IpConnectivityMetrics extends SystemService {
} }
@Override @Override
public boolean registerNetdEventCallback(INetdEventCallback callback) { public boolean addNetdEventCallback(int callerType, INetdEventCallback callback) {
enforceNetdEventListeningPermission(); enforceNetdEventListeningPermission();
if (mNetdListener == null) { if (mNetdListener == null) {
return false; return false;
} }
return mNetdListener.registerNetdEventCallback(callback); return mNetdListener.addNetdEventCallback(callerType, callback);
} }
@Override @Override
public boolean unregisterNetdEventCallback() { public boolean removeNetdEventCallback(int callerType) {
enforceNetdEventListeningPermission(); enforceNetdEventListeningPermission();
if (mNetdListener == null) { if (mNetdListener == null) {
// if the service is null, we aren't registered anyway // if the service is null, we aren't registered anyway
return true; return true;
} }
return mNetdListener.unregisterNetdEventCallback(); return mNetdListener.removeNetdEventCallback(callerType);
} }
}; };

View File

@@ -98,21 +98,55 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
@GuardedBy("this") @GuardedBy("this")
private final TokenBucket mConnectTb = private final TokenBucket mConnectTb =
new TokenBucket(CONNECT_LATENCY_FILL_RATE, CONNECT_LATENCY_BURST_LIMIT); new TokenBucket(CONNECT_LATENCY_FILL_RATE, CONNECT_LATENCY_BURST_LIMIT);
// Callback should only be registered/unregistered when logging is being enabled/disabled in DPM
// by the device owner. It's DevicePolicyManager's responsibility to ensure that.
@GuardedBy("this")
private INetdEventCallback mNetdEventCallback;
public synchronized boolean registerNetdEventCallback(INetdEventCallback callback) {
mNetdEventCallback = callback; /**
* There are only 2 possible callbacks.
*
* mNetdEventCallbackList[CALLBACK_CALLER_DEVICE_POLICY].
* Callback registered/unregistered when logging is being enabled/disabled in DPM
* by the device owner. It's DevicePolicyManager's responsibility to ensure that.
*
* mNetdEventCallbackList[CALLBACK_CALLER_NETWORK_WATCHLIST]
* Callback registered/unregistered by NetworkWatchlistService.
*/
@GuardedBy("this")
private static final int[] ALLOWED_CALLBACK_TYPES = {
INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY,
INetdEventCallback.CALLBACK_CALLER_NETWORK_WATCHLIST
};
@GuardedBy("this")
private INetdEventCallback[] mNetdEventCallbackList =
new INetdEventCallback[ALLOWED_CALLBACK_TYPES.length];
public synchronized boolean addNetdEventCallback(int callerType, INetdEventCallback callback) {
if (!isValidCallerType(callerType)) {
Log.e(TAG, "Invalid caller type: " + callerType);
return false;
}
mNetdEventCallbackList[callerType] = callback;
return true; return true;
} }
public synchronized boolean unregisterNetdEventCallback() { public synchronized boolean removeNetdEventCallback(int callerType) {
mNetdEventCallback = null; if (!isValidCallerType(callerType)) {
Log.e(TAG, "Invalid caller type: " + callerType);
return false;
}
mNetdEventCallbackList[callerType] = null;
return true; return true;
} }
private static boolean isValidCallerType(int callerType) {
for (int i = 0; i < ALLOWED_CALLBACK_TYPES.length; i++) {
if (callerType == ALLOWED_CALLBACK_TYPES[i]) {
return true;
}
}
return false;
}
public NetdEventListenerService(Context context) { public NetdEventListenerService(Context context) {
this(context.getSystemService(ConnectivityManager.class)); this(context.getSystemService(ConnectivityManager.class));
} }
@@ -169,8 +203,10 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
getMetricsForNetwork(timestamp, netId).addDnsResult(eventType, returnCode, latencyMs); getMetricsForNetwork(timestamp, netId).addDnsResult(eventType, returnCode, latencyMs);
if (mNetdEventCallback != null) { for (INetdEventCallback callback : mNetdEventCallbackList) {
mNetdEventCallback.onDnsEvent(hostname, ipAddresses, ipAddressesCount, timestamp, uid); if (callback != null) {
callback.onDnsEvent(hostname, ipAddresses, ipAddressesCount, timestamp, uid);
}
} }
} }
@@ -184,8 +220,14 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
getMetricsForNetwork(timestamp, netId).addConnectResult(error, latencyMs, ipAddr); getMetricsForNetwork(timestamp, netId).addConnectResult(error, latencyMs, ipAddr);
if (mNetdEventCallback != null) { for (INetdEventCallback callback : mNetdEventCallbackList) {
mNetdEventCallback.onConnectEvent(ipAddr, port, timestamp, uid); if (callback != null) {
// TODO(rickywai): Remove this checking to collect ip in watchlist.
if (callback ==
mNetdEventCallbackList[INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY]) {
callback.onConnectEvent(ipAddr, port, timestamp, uid);
}
}
} }
} }

View File

@@ -107,7 +107,8 @@ final class NetworkLogger {
return false; return false;
} }
try { try {
if (mIpConnectivityMetrics.registerNetdEventCallback(mNetdEventCallback)) { if (mIpConnectivityMetrics.addNetdEventCallback(
INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY, mNetdEventCallback)) {
mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
/* allowIo */ false); /* allowIo */ false);
mHandlerThread.start(); mHandlerThread.start();
@@ -138,7 +139,8 @@ final class NetworkLogger {
// logging is forcefully disabled even if unregistering fails // logging is forcefully disabled even if unregistering fails
return true; return true;
} }
return mIpConnectivityMetrics.unregisterNetdEventCallback(); return mIpConnectivityMetrics.removeNetdEventCallback(
INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY);
} catch (RemoteException re) { } catch (RemoteException re) {
Slog.wtf(TAG, "Failed to make remote calls to unregister the callback", re); Slog.wtf(TAG, "Failed to make remote calls to unregister the callback", re);
return true; return true;

View File

@@ -3150,7 +3150,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// setUp() adds a secondary user for CALLER_USER_HANDLE. Remove it as otherwise the // setUp() adds a secondary user for CALLER_USER_HANDLE. Remove it as otherwise the
// feature is disabled because there are non-affiliated secondary users. // feature is disabled because there are non-affiliated secondary users.
getServices().removeUser(DpmMockContext.CALLER_USER_HANDLE); getServices().removeUser(DpmMockContext.CALLER_USER_HANDLE);
when(getServices().iipConnectivityMetrics.registerNetdEventCallback(anyObject())) when(getServices().iipConnectivityMetrics.addNetdEventCallback(anyInt(), anyObject()))
.thenReturn(true); .thenReturn(true);
// No logs were retrieved so far. // No logs were retrieved so far.