Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e945ea64 authored by Liz Prucka's avatar Liz Prucka Committed by Android (Google) Code Review
Browse files

Merge "[ID] Add Network Logging" into main

parents f463b1bf b4ebf52f
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -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;
    }

+5 −0
Original line number Diff line number Diff line
@@ -17,6 +17,11 @@
package com.android.server.security.intrusiondetection;

public interface DataSource {
    /**
     * Initialize the data source.
     */
    boolean initialize();

    /**
     * Enable the data collection.
     */
+42 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}
+134 −0
Original line number Diff line number Diff line
/*
 * 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());
    }
}
+21 −7
Original line number Diff line number Diff line
@@ -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();
    }