summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Liz Prucka <lizprucka@google.com> 2024-11-03 15:23:42 +0000
committer Liz Prucka <lizprucka@google.com> 2024-11-22 16:14:03 +0000
commitb4ebf52f1f12bca778a1bd7e51ef010bc6eec1e2 (patch)
tree0e1dfa311a98657ab20ec774d728b2b4aecf1aef
parent5f89fa38e3ba65d1d6704e84fba5e6e0cc90fce9 (diff)
[ID] Add Network Logging
Added an AdminReceiver to receive DeviceAdmin callbacks. NetworkLogSource receives NetworkLog callbacks from the admin receiver, and returns data to the DataAggregator. The network log source architecture is documented at go/forensic-datasource-docs. Added a permission check in SecurityLog initialization to prevent silent failures. Bug: 365994454 Test: atest IntrusionDetectionServiceTest Flag: android.security.afl_api Ignore-AOSP-First: security feature Change-Id: I4a5eaa4b6f4e2ce244f61250f39fb66bc0550326
-rw-r--r--services/core/java/com/android/server/security/intrusiondetection/DataAggregator.java14
-rw-r--r--services/core/java/com/android/server/security/intrusiondetection/DataSource.java5
-rw-r--r--services/core/java/com/android/server/security/intrusiondetection/IntrusionDetectionAdminReceiver.java42
-rw-r--r--services/core/java/com/android/server/security/intrusiondetection/NetworkLogSource.java134
-rw-r--r--services/core/java/com/android/server/security/intrusiondetection/SecurityLogSource.java28
5 files changed, 215 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/security/intrusiondetection/DataAggregator.java b/services/core/java/com/android/server/security/intrusiondetection/DataAggregator.java
index 06e9dcdcbedd..0ea88e8523f0 100644
--- a/services/core/java/com/android/server/security/intrusiondetection/DataAggregator.java
+++ b/services/core/java/com/android/server/security/intrusiondetection/DataAggregator.java
@@ -36,6 +36,9 @@ public class DataAggregator {
private static final int MSG_DISABLE = 2;
private static final int STORED_EVENTS_SIZE_LIMIT = 1024;
+ private static final IntrusionDetectionAdminReceiver ADMIN_RECEIVER =
+ new IntrusionDetectionAdminReceiver();
+
private final IntrusionDetectionService mIntrusionDetectionService;
private final ArrayList<DataSource> mDataSources;
@@ -60,10 +63,19 @@ public class DataAggregator {
* Initialize DataSources
* @return Whether the initialization succeeds.
*/
- // TODO: Add the corresponding data sources
public boolean initialize() {
SecurityLogSource securityLogSource = new SecurityLogSource(mContext, this);
mDataSources.add(securityLogSource);
+
+ NetworkLogSource networkLogSource = new NetworkLogSource(mContext, this);
+ ADMIN_RECEIVER.setNetworkLogEventCallback(networkLogSource);
+ mDataSources.add(networkLogSource);
+
+ for (DataSource ds : mDataSources) {
+ if (!ds.initialize()) {
+ return false;
+ }
+ }
return true;
}
diff --git a/services/core/java/com/android/server/security/intrusiondetection/DataSource.java b/services/core/java/com/android/server/security/intrusiondetection/DataSource.java
index 0bc448245b76..61fac46be82d 100644
--- a/services/core/java/com/android/server/security/intrusiondetection/DataSource.java
+++ b/services/core/java/com/android/server/security/intrusiondetection/DataSource.java
@@ -18,6 +18,11 @@ package com.android.server.security.intrusiondetection;
public interface DataSource {
/**
+ * Initialize the data source.
+ */
+ boolean initialize();
+
+ /**
* Enable the data collection.
*/
void enable();
diff --git a/services/core/java/com/android/server/security/intrusiondetection/IntrusionDetectionAdminReceiver.java b/services/core/java/com/android/server/security/intrusiondetection/IntrusionDetectionAdminReceiver.java
new file mode 100644
index 000000000000..dba7374fe02a
--- /dev/null
+++ b/services/core/java/com/android/server/security/intrusiondetection/IntrusionDetectionAdminReceiver.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 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 com.android.server.security.intrusiondetection;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Slog;
+
+public class IntrusionDetectionAdminReceiver extends DeviceAdminReceiver {
+ private static final String TAG = "IntrusionDetectionAdminReceiver";
+
+ private static NetworkLogSource sNetworkLogSource;
+
+ @Override
+ public void onNetworkLogsAvailable(
+ Context context, Intent intent, long batchToken, int networkLogsCount) {
+ if (sNetworkLogSource != null) {
+ sNetworkLogSource.onNetworkLogsAvailable(batchToken);
+ } else {
+ Slog.w(TAG, "Network log receiver is not initialized");
+ }
+ }
+
+ public void setNetworkLogEventCallback(NetworkLogSource networkLogSource) {
+ sNetworkLogSource = networkLogSource;
+ }
+}
diff --git a/services/core/java/com/android/server/security/intrusiondetection/NetworkLogSource.java b/services/core/java/com/android/server/security/intrusiondetection/NetworkLogSource.java
new file mode 100644
index 000000000000..1c93d3f9c6a1
--- /dev/null
+++ b/services/core/java/com/android/server/security/intrusiondetection/NetworkLogSource.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 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 com.android.server.security.intrusiondetection;
+
+import android.app.admin.ConnectEvent;
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.DnsEvent;
+import android.app.admin.NetworkEvent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.security.intrusiondetection.IntrusionDetectionEvent;
+import android.util.Slog;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class NetworkLogSource implements DataSource {
+
+ private static final String TAG = "IntrusionDetectionEvent NetworkLogSource";
+
+ private DevicePolicyManager mDpm;
+ private ComponentName mAdmin;
+ private DataAggregator mDataAggregator;
+
+ public NetworkLogSource(Context context, DataAggregator dataAggregator) {
+ mDataAggregator = dataAggregator;
+ mDpm = context.getSystemService(DevicePolicyManager.class);
+ mAdmin = new ComponentName(context, IntrusionDetectionAdminReceiver.class);
+ }
+
+ @Override
+ public boolean initialize() {
+ try {
+ if (!mDpm.isAdminActive(mAdmin)) {
+ Slog.e(TAG, "Admin " + mAdmin.flattenToString() + "is not active admin");
+ return false;
+ }
+ } catch (SecurityException e) {
+ Slog.e(TAG, "Security exception in initialize: ", e);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void enable() {
+ enableNetworkLog();
+ }
+
+ @Override
+ public void disable() {
+ disableNetworkLog();
+ }
+
+ private void enableNetworkLog() {
+ if (!isNetworkLogEnabled()) {
+ mDpm.setNetworkLoggingEnabled(mAdmin, true);
+ }
+ }
+
+ private void disableNetworkLog() {
+ if (isNetworkLogEnabled()) {
+ mDpm.setNetworkLoggingEnabled(mAdmin, false);
+ }
+ }
+
+ private boolean isNetworkLogEnabled() {
+ return mDpm.isNetworkLoggingEnabled(mAdmin);
+ }
+
+ /**
+ * Retrieve network logs when onNetworkLogsAvailable callback is received.
+ *
+ * @param batchToken The token representing the current batch of network logs.
+ */
+ public void onNetworkLogsAvailable(long batchToken) {
+ List<NetworkEvent> events;
+ try {
+ events = mDpm.retrieveNetworkLogs(mAdmin, batchToken);
+ } catch (SecurityException e) {
+ Slog.e(
+ TAG,
+ "Admin "
+ + mAdmin.flattenToString()
+ + "does not have permission to retrieve network logs",
+ e);
+ return;
+ }
+ if (events == null) {
+ if (!isNetworkLogEnabled()) {
+ Slog.w(TAG, "Network logging is disabled");
+ } else {
+ Slog.e(TAG, "Invalid batch token: " + batchToken);
+ }
+ return;
+ }
+
+ List<IntrusionDetectionEvent> intrusionDetectionEvents =
+ events.stream()
+ .filter(event -> event != null)
+ .map(event -> toIntrusionDetectionEvent(event))
+ .collect(Collectors.toList());
+ mDataAggregator.addBatchData(intrusionDetectionEvents);
+ }
+
+ private IntrusionDetectionEvent toIntrusionDetectionEvent(NetworkEvent event) {
+ if (event instanceof DnsEvent) {
+ DnsEvent dnsEvent = (DnsEvent) event;
+ return new IntrusionDetectionEvent(dnsEvent);
+ } else if (event instanceof ConnectEvent) {
+ ConnectEvent connectEvent = (ConnectEvent) event;
+ return new IntrusionDetectionEvent(connectEvent);
+ }
+ throw new IllegalArgumentException(
+ "Invalid event type with ID: "
+ + event.getId()
+ + "from package: "
+ + event.getPackageName());
+ }
+}
diff --git a/services/core/java/com/android/server/security/intrusiondetection/SecurityLogSource.java b/services/core/java/com/android/server/security/intrusiondetection/SecurityLogSource.java
index 226f9d879cab..c5f736e383b2 100644
--- a/services/core/java/com/android/server/security/intrusiondetection/SecurityLogSource.java
+++ b/services/core/java/com/android/server/security/intrusiondetection/SecurityLogSource.java
@@ -22,6 +22,7 @@ import android.app.admin.DevicePolicyManager;
import android.app.admin.SecurityLog.SecurityEvent;
import android.content.Context;
import android.security.intrusiondetection.IntrusionDetectionEvent;
+import android.util.Slog;
import java.util.List;
import java.util.concurrent.Executor;
@@ -33,7 +34,7 @@ public class SecurityLogSource implements DataSource {
private static final String TAG = "IntrusionDetection SecurityLogSource";
- private SecurityEventCallback mEventCallback = new SecurityEventCallback();
+ private SecurityEventCallback mEventCallback;
private DevicePolicyManager mDpm;
private Executor mExecutor;
private DataAggregator mDataAggregator;
@@ -42,9 +43,26 @@ public class SecurityLogSource implements DataSource {
mDataAggregator = dataAggregator;
mDpm = context.getSystemService(DevicePolicyManager.class);
mExecutor = Executors.newSingleThreadExecutor();
+ }
+
+ @Override
+ public boolean initialize() {
+ // Confirm caller is system and the device is managed. Otherwise logs will
+ // be redacted.
+ try {
+ if (!mDpm.isDeviceManaged()) {
+ Slog.e(TAG, "Caller does not have device owner permissions");
+ return false;
+ }
+ } catch (SecurityException e) {
+ Slog.e(TAG, "Security exception in initialize: ", e);
+ return false;
+ }
mEventCallback = new SecurityEventCallback();
+ return true;
}
+
@Override
@RequiresPermission(permission.MANAGE_DEVICE_POLICY_AUDIT_LOGGING)
public void enable() {
@@ -72,12 +90,8 @@ public class SecurityLogSource implements DataSource {
}
}
- /**
- * Check if security audit logging is enabled for the caller.
- *
- * @return Whether security audit logging is enabled.
- */
- public boolean isAuditLogEnabled() {
+ @RequiresPermission(permission.MANAGE_DEVICE_POLICY_AUDIT_LOGGING)
+ private boolean isAuditLogEnabled() {
return mDpm.isAuditLogEnabled();
}