blob: fb7f573d5535b462631f73cee05c7b8146df4b01 [file] [log] [blame]
/*
* Copyright (C) 2016 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.app.admin;
import android.annotation.IntDef;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.EventLog.Event;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
/**
* Definitions for working with security logs.
*
* <p>Device owner apps can control the logging with
* {@link DevicePolicyManager#setSecurityLoggingEnabled}. When security logs are enabled, device
* owner apps receive periodic callbacks from {@link DeviceAdminReceiver#onSecurityLogsAvailable},
* at which time new batch of logs can be collected via
* {@link DevicePolicyManager#retrieveSecurityLogs}. {@link SecurityEvent} describes the type and
* format of security logs being collected.
*/
public class SecurityLog {
private static final String PROPERTY_LOGGING_ENABLED = "persist.logd.security";
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "TAG_" }, value = {
TAG_ADB_SHELL_INTERACTIVE,
TAG_ADB_SHELL_CMD,
TAG_SYNC_RECV_FILE,
TAG_SYNC_SEND_FILE,
TAG_APP_PROCESS_START,
TAG_KEYGUARD_DISMISSED,
TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT,
TAG_KEYGUARD_SECURED,
TAG_OS_STARTUP,
TAG_OS_SHUTDOWN,
TAG_LOGGING_STARTED,
TAG_LOGGING_STOPPED,
TAG_MEDIA_MOUNT,
TAG_MEDIA_UNMOUNT,
TAG_LOG_BUFFER_SIZE_CRITICAL,
TAG_PASSWORD_EXPIRATION_SET,
TAG_PASSWORD_COMPLEXITY_SET,
TAG_PASSWORD_HISTORY_LENGTH_SET,
TAG_MAX_SCREEN_LOCK_TIMEOUT_SET,
TAG_MAX_PASSWORD_ATTEMPTS_SET,
TAG_KEYGUARD_DISABLED_FEATURES_SET,
TAG_REMOTE_LOCK,
TAG_USER_RESTRICTION_ADDED,
TAG_USER_RESTRICTION_REMOVED,
TAG_WIPE_FAILURE,
TAG_KEY_GENERATED,
TAG_KEY_IMPORT,
TAG_KEY_DESTRUCTION,
TAG_CERT_AUTHORITY_INSTALLED,
TAG_CERT_AUTHORITY_REMOVED,
TAG_CRYPTO_SELF_TEST_COMPLETED,
TAG_KEY_INTEGRITY_VIOLATION,
TAG_CERT_VALIDATION_FAILURE,
TAG_CAMERA_POLICY_SET
})
public @interface SecurityLogTag {}
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "LEVEL_" }, value = {
LEVEL_INFO,
LEVEL_WARNING,
LEVEL_ERROR
})
public @interface SecurityLogLevel {}
/**
* Indicates that an ADB interactive shell was opened via "adb shell".
* There is no extra payload in the log event.
*/
public static final int TAG_ADB_SHELL_INTERACTIVE =
SecurityLogTags.SECURITY_ADB_SHELL_INTERACTIVE;
/**
* Indicates that a shell command was issued over ADB via {@code adb shell <command>}
* The log entry contains a {@code String} payload containing the shell command, accessible
* via {@link SecurityEvent#getData()}. If security logging is enabled on organization-owned
* managed profile devices, the shell command will be redacted to an empty string.
*/
public static final int TAG_ADB_SHELL_CMD = SecurityLogTags.SECURITY_ADB_SHELL_COMMAND;
/**
* Indicates that a file was pulled from the device via the adb daemon, for example via
* {@code adb pull}. The log entry contains a {@code String} payload containing the path of the
* pulled file on the device, accessible via {@link SecurityEvent#getData()}.
*/
public static final int TAG_SYNC_RECV_FILE = SecurityLogTags.SECURITY_ADB_SYNC_RECV;
/**
* Indicates that a file was pushed to the device via the adb daemon, for example via
* {@code adb push}. The log entry contains a {@code String} payload containing the destination
* path of the pushed file, accessible via {@link SecurityEvent#getData()}.
*/
public static final int TAG_SYNC_SEND_FILE = SecurityLogTags.SECURITY_ADB_SYNC_SEND;
/**
* Indicates that an app process was started. The log entry contains the following
* information about the process encapsulated in an {@link Object} array, accessible via
* {@link SecurityEvent#getData()}:
* <li> [0] process name ({@code String})
* <li> [1] exact start time in milliseconds according to {@code System.currentTimeMillis()}
* ({@code Long})
* <li> [2] app uid ({@code Integer})
* <li> [3] app pid ({@code Integer})
* <li> [4] seinfo tag ({@code String})
* <li> [5] SHA-256 hash of the base APK in hexadecimal ({@code String})
* If security logging is enabled on organization-owned managed profile devices, only events
* happening inside the managed profile will be visible.
*/
public static final int TAG_APP_PROCESS_START = SecurityLogTags.SECURITY_APP_PROCESS_START;
/**
* Indicates that keyguard has been dismissed. This event is only logged if the device
* has a secure keyguard. It is logged regardless of how keyguard is dismissed, including
* via PIN/pattern/password, biometrics or via a trust agent.
* There is no extra payload in the log event.
* @see #TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT
*/
public static final int TAG_KEYGUARD_DISMISSED = SecurityLogTags.SECURITY_KEYGUARD_DISMISSED;
/**
* Indicates that there has been an authentication attempt to dismiss the keyguard. The log
* entry contains the following information about the attempt encapsulated in an {@link Object}
* array, accessible via {@link SecurityEvent#getData()}:
* <li> [0] attempt result ({@code Integer}, 1 for successful, 0 for unsuccessful)
* <li> [1] strength of authentication method ({@code Integer}, 1 if strong authentication
* method was used, 0 otherwise)
*/
public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT =
SecurityLogTags.SECURITY_KEYGUARD_DISMISS_AUTH_ATTEMPT;
/**
* Indicates that the device has been locked, either by the user or by a timeout. There is no
* extra payload in the log event.
*/
public static final int TAG_KEYGUARD_SECURED = SecurityLogTags.SECURITY_KEYGUARD_SECURED;
/**
* Indicates that the Android OS has started. The log entry contains the following information
* about the startup time software integrity check encapsulated in an {@link Object} array,
* accessible via {@link SecurityEvent#getData()}:
* <li> [0] Verified Boot state ({@code String})
* <li> [1] dm-verity mode ({@code String}).
* <p>Verified Boot state can be one of the following:
* <li> {@code green} indicates that there is a full chain of trust extending from the
* bootloader to verified partitions including the bootloader, boot partition, and all verified
* partitions.
* <li> {@code yellow} indicates that the boot partition has been verified using the embedded
* certificate and the signature is valid.
* <li> {@code orange} indicates that the device may be freely modified. Device integrity is
* left to the user to verify out-of-band.
* <p>dm-verity mode can be one of the following:
* <li> {@code enforcing} indicates that the device will be restarted when corruption is
* detected.
* <li> {@code eio} indicates that an I/O error will be returned for an attempt to read
* corrupted data blocks.
* For details see Verified Boot documentation.
*/
public static final int TAG_OS_STARTUP = SecurityLogTags.SECURITY_OS_STARTUP;
/**
* Indicates that the Android OS has shutdown. There is no extra payload in the log event.
*/
public static final int TAG_OS_SHUTDOWN = SecurityLogTags.SECURITY_OS_SHUTDOWN;
/**
* Indicates start-up of audit logging. There is no extra payload in the log event.
*/
public static final int TAG_LOGGING_STARTED = SecurityLogTags.SECURITY_LOGGING_STARTED;
/**
* Indicates shutdown of audit logging. There is no extra payload in the log event.
*/
public static final int TAG_LOGGING_STOPPED = SecurityLogTags.SECURITY_LOGGING_STOPPED;
/**
* Indicates that removable media has been mounted on the device. The log entry contains the
* following information about the event, encapsulated in an {@link Object} array and
* accessible via {@link SecurityEvent#getData()}:
* <li> [0] mount point ({@code String})
* <li> [1] volume label ({@code String}). Redacted to empty string on organization-owned
* managed profile devices.
*/
public static final int TAG_MEDIA_MOUNT = SecurityLogTags.SECURITY_MEDIA_MOUNTED;
/**
* Indicates that removable media was unmounted from the device. The log entry contains the
* following information about the event, encapsulated in an {@link Object} array and
* accessible via {@link SecurityEvent#getData()}:
* <li> [0] mount point ({@code String})
* <li> [1] volume label ({@code String}). Redacted to empty string on organization-owned
* managed profile devices.
*/
public static final int TAG_MEDIA_UNMOUNT = SecurityLogTags.SECURITY_MEDIA_UNMOUNTED;
/**
* Indicates that the audit log buffer has reached 90% of its capacity. There is no extra
* payload in the log event.
*/
public static final int TAG_LOG_BUFFER_SIZE_CRITICAL =
SecurityLogTags.SECURITY_LOG_BUFFER_SIZE_CRITICAL;
/**
* Indicates that an admin has set a password expiration timeout. The log entry contains the
* following information about the event, encapsulated in an {@link Object} array and accessible
* via {@link SecurityEvent#getData()}:
* <li> [0] admin package name ({@code String})
* <li> [1] admin user ID ({@code Integer})
* <li> [2] target user ID ({@code Integer})
* <li> [3] new password expiration timeout in milliseconds ({@code Long}).
* @see DevicePolicyManager#setPasswordExpirationTimeout(ComponentName, long)
*/
public static final int TAG_PASSWORD_EXPIRATION_SET =
SecurityLogTags.SECURITY_PASSWORD_EXPIRATION_SET;
/**
* Indicates that an admin has set a requirement for password complexity. The log entry contains
* the following information about the event, encapsulated in an {@link Object} array and
* accessible via {@link SecurityEvent#getData()}:
* <li> [0] admin package name ({@code String})
* <li> [1] admin user ID ({@code Integer})
* <li> [2] target user ID ({@code Integer})
* <li> [3] minimum password length ({@code Integer})
* <li> [4] password quality constraint ({@code Integer})
* <li> [5] minimum number of letters ({@code Integer})
* <li> [6] minimum number of non-letters ({@code Integer})
* <li> [7] minimum number of digits ({@code Integer})
* <li> [8] minimum number of uppercase letters ({@code Integer})
* <li> [9] minimum number of lowercase letters ({@code Integer})
* <li> [10] minimum number of symbols ({@code Integer})
*
* @see DevicePolicyManager#setPasswordMinimumLength(ComponentName, int)
* @see DevicePolicyManager#setPasswordQuality(ComponentName, int)
* @see DevicePolicyManager#setPasswordMinimumLetters(ComponentName, int)
* @see DevicePolicyManager#setPasswordMinimumNonLetter(ComponentName, int)
* @see DevicePolicyManager#setPasswordMinimumLowerCase(ComponentName, int)
* @see DevicePolicyManager#setPasswordMinimumUpperCase(ComponentName, int)
* @see DevicePolicyManager#setPasswordMinimumNumeric(ComponentName, int)
* @see DevicePolicyManager#setPasswordMinimumSymbols(ComponentName, int)
*/
public static final int TAG_PASSWORD_COMPLEXITY_SET =
SecurityLogTags.SECURITY_PASSWORD_COMPLEXITY_SET;
/**
* Indicates that an admin has set a password history length. The log entry contains the
* following information about the event encapsulated in an {@link Object} array, accessible
* via {@link SecurityEvent#getData()}:
* <li> [0] admin package name ({@code String})
* <li> [1] admin user ID ({@code Integer})
* <li> [2] target user ID ({@code Integer})
* <li> [3] new password history length value ({@code Integer})
* @see DevicePolicyManager#setPasswordHistoryLength(ComponentName, int)
*/
public static final int TAG_PASSWORD_HISTORY_LENGTH_SET =
SecurityLogTags.SECURITY_PASSWORD_HISTORY_LENGTH_SET;
/**
* Indicates that an admin has set a maximum screen lock timeout. The log entry contains the
* following information about the event encapsulated in an {@link Object} array, accessible
* via {@link SecurityEvent#getData()}:
* <li> [0] admin package name ({@code String})
* <li> [1] admin user ID ({@code Integer})
* <li> [2] target user ID ({@code Integer})
* <li> [3] new screen lock timeout in milliseconds ({@code Long})
* @see DevicePolicyManager#setMaximumTimeToLock(ComponentName, long)
*/
public static final int TAG_MAX_SCREEN_LOCK_TIMEOUT_SET =
SecurityLogTags.SECURITY_MAX_SCREEN_LOCK_TIMEOUT_SET;
/**
* Indicates that an admin has set a maximum number of failed password attempts before wiping
* data. The log entry contains the following information about the event encapsulated in an
* {@link Object} array, accessible via {@link SecurityEvent#getData()}:
* <li> [0] admin package name ({@code String})
* <li> [1] admin user ID ({@code Integer})
* <li> [2] target user ID ({@code Integer})
* <li> [3] new maximum number of failed password attempts ({@code Integer})
* @see DevicePolicyManager#setMaximumFailedPasswordsForWipe(ComponentName, int)
*/
public static final int TAG_MAX_PASSWORD_ATTEMPTS_SET =
SecurityLogTags.SECURITY_MAX_PASSWORD_ATTEMPTS_SET;
/**
* Indicates that an admin has set disabled keyguard features. The log entry contains the
* following information about the event encapsulated in an {@link Object} array, accessible via
* {@link SecurityEvent#getData()}:
* <li> [0] admin package name ({@code String})
* <li> [1] admin user ID ({@code Integer})
* <li> [2] target user ID ({@code Integer})
* <li> [3] disabled keyguard feature mask ({@code Integer}).
* @see DevicePolicyManager#setKeyguardDisabledFeatures(ComponentName, int)
*/
public static final int TAG_KEYGUARD_DISABLED_FEATURES_SET =
SecurityLogTags.SECURITY_KEYGUARD_DISABLED_FEATURES_SET;
/**
* Indicates that an admin remotely locked the device or profile. The log entry contains the
* following information about the event encapsulated in an {@link Object} array, accessible via
* {@link SecurityEvent#getData()}:
* <li> [0] admin package name ({@code String}),
* <li> [1] admin user ID ({@code Integer}).
* <li> [2] target user ID ({@code Integer})
*/
public static final int TAG_REMOTE_LOCK = SecurityLogTags.SECURITY_REMOTE_LOCK;
/**
* Indicates a failure to wipe device or user data. There is no extra payload in the log event.
*/
public static final int TAG_WIPE_FAILURE = SecurityLogTags.SECURITY_WIPE_FAILED;
/**
* Indicates that an authentication key was generated. The log entry contains the following
* information about the event, encapsulated in an {@link Object} array and accessible via
* {@link SecurityEvent#getData()}:
* <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
* <li> [1] alias of the key ({@code String})
* <li> [2] requesting process uid ({@code Integer}).
*
* If security logging is enabled on organization-owned managed profile devices, only events
* happening inside the managed profile will be visible.
*/
public static final int TAG_KEY_GENERATED =
SecurityLogTags.SECURITY_KEY_GENERATED;
/**
* Indicates that a cryptographic key was imported. The log entry contains the following
* information about the event, encapsulated in an {@link Object} array and accessible via
* {@link SecurityEvent#getData()}:
* <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
* <li> [1] alias of the key ({@code String})
* <li> [2] requesting process uid ({@code Integer}).
*
* If security logging is enabled on organization-owned managed profile devices, only events
* happening inside the managed profile will be visible.
*/
public static final int TAG_KEY_IMPORT = SecurityLogTags.SECURITY_KEY_IMPORTED;
/**
* Indicates that a cryptographic key was destroyed. The log entry contains the following
* information about the event, encapsulated in an {@link Object} array and accessible via
* {@link SecurityEvent#getData()}:
* <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
* <li> [1] alias of the key ({@code String})
* <li> [2] requesting process uid ({@code Integer}).
*
* If security logging is enabled on organization-owned managed profile devices, only events
* happening inside the managed profile will be visible.
*/
public static final int TAG_KEY_DESTRUCTION = SecurityLogTags.SECURITY_KEY_DESTROYED;
/**
* Indicates that a new root certificate has been installed into system's trusted credential
* storage. The log entry contains the following information about the event, encapsulated in an
* {@link Object} array and accessible via {@link SecurityEvent#getData()}:
* <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
* <li> [1] subject of the certificate ({@code String}).
* <li> [2] which user the certificate is installed for ({@code Integer}), only available from
* version {@link android.os.Build.VERSION_CODES#R}.
*
* If security logging is enabled on organization-owned managed profile devices, only events
* happening inside the managed profile will be visible.
*/
public static final int TAG_CERT_AUTHORITY_INSTALLED =
SecurityLogTags.SECURITY_CERT_AUTHORITY_INSTALLED;
/**
* Indicates that a new root certificate has been removed from system's trusted credential
* storage. The log entry contains the following information about the event, encapsulated in an
* {@link Object} array and accessible via {@link SecurityEvent#getData()}:
* <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
* <li> [1] subject of the certificate ({@code String}).
* <li> [2] which user the certificate is removed from ({@code Integer}), only available from
* version {@link android.os.Build.VERSION_CODES#R}.
*
* If security logging is enabled on organization-owned managed profile devices, only events
* happening inside the managed profile will be visible.
*/
public static final int TAG_CERT_AUTHORITY_REMOVED =
SecurityLogTags.SECURITY_CERT_AUTHORITY_REMOVED;
/**
* Indicates that an admin has set a user restriction. The log entry contains the following
* information about the event, encapsulated in an {@link Object} array and accessible via
* {@link SecurityEvent#getData()}:
* <li> [0] admin package name ({@code String})
* <li> [1] admin user ID ({@code Integer})
* <li> [2] user restriction ({@code String})
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
*/
public static final int TAG_USER_RESTRICTION_ADDED =
SecurityLogTags.SECURITY_USER_RESTRICTION_ADDED;
/**
* Indicates that an admin has removed a user restriction. The log entry contains the following
* information about the event, encapsulated in an {@link Object} array and accessible via
* {@link SecurityEvent#getData()}:
* <li> [0] admin package name ({@code String})
* <li> [1] admin user ID ({@code Integer})
* <li> [2] user restriction ({@code String})
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
*/
public static final int TAG_USER_RESTRICTION_REMOVED =
SecurityLogTags.SECURITY_USER_RESTRICTION_REMOVED;
/**
* Indicates that cryptographic functionality self test has completed. The log entry contains an
* {@code Integer} payload, indicating the result of the test (0 if the test failed, 1 if
* succeeded) and accessible via {@link SecurityEvent#getData()}.
*/
public static final int TAG_CRYPTO_SELF_TEST_COMPLETED =
SecurityLogTags.SECURITY_CRYPTO_SELF_TEST_COMPLETED;
/**
* Indicates a failed cryptographic key integrity check. The log entry contains the following
* information about the event, encapsulated in an {@link Object} array and accessible via
* {@link SecurityEvent#getData()}:
* <li> [0] alias of the key ({@code String})
* <li> [1] owner application uid ({@code Integer}).
*
* If security logging is enabled on organization-owned managed profile devices, only events
* happening inside the managed profile will be visible.
*/
public static final int TAG_KEY_INTEGRITY_VIOLATION =
SecurityLogTags.SECURITY_KEY_INTEGRITY_VIOLATION;
/**
* Indicates a failure to validate X.509v3 certificate. The log entry contains a {@code String}
* payload indicating the failure reason, accessible via {@link SecurityEvent#getData()}.
*/
public static final int TAG_CERT_VALIDATION_FAILURE =
SecurityLogTags.SECURITY_CERT_VALIDATION_FAILURE;
/**
* Indicates that the admin has set policy to disable camera.
* The log entry contains the following information about the event, encapsulated in an
* {@link Object} array and accessible via {@link SecurityEvent#getData()}:
* <li> [0] admin package name ({@code String})
* <li> [1] admin user ID ({@code Integer})
* <li> [2] target user ID ({@code Integer})
* <li> [3] whether the camera is disabled or not ({@code Integer}, 1 if it's disabled,
* 0 if enabled)
*/
public static final int TAG_CAMERA_POLICY_SET =
SecurityLogTags.SECURITY_CAMERA_POLICY_SET;
/**
* Event severity level indicating that the event corresponds to normal workflow.
*/
public static final int LEVEL_INFO = 1;
/**
* Event severity level indicating that the event may require admin attention.
*/
public static final int LEVEL_WARNING = 2;
/**
* Event severity level indicating that the event requires urgent admin action.
*/
public static final int LEVEL_ERROR = 3;
/**
* Returns if security logging is enabled. Log producers should only write new logs if this is
* true. Under the hood this is the logical AND of whether device owner exists and whether
* it enables logging by setting the system property {@link #PROPERTY_LOGGING_ENABLED}.
* @hide
*/
public static native boolean isLoggingEnabled();
/**
* @hide
*/
public static void setLoggingEnabledProperty(boolean enabled) {
SystemProperties.set(PROPERTY_LOGGING_ENABLED, enabled ? "true" : "false");
}
/**
* @hide
*/
public static boolean getLoggingEnabledProperty() {
return SystemProperties.getBoolean(PROPERTY_LOGGING_ENABLED, false);
}
/**
* A class representing a security event log entry.
*/
public static final class SecurityEvent implements Parcelable {
private Event mEvent;
private long mId;
/**
* Constructor used by native classes to generate SecurityEvent instances.
* @hide
*/
@UnsupportedAppUsage
/* package */ SecurityEvent(byte[] data) {
this(0, data);
}
/**
* Constructor used by Parcelable.Creator to generate SecurityEvent instances.
* @hide
*/
/* package */ SecurityEvent(Parcel source) {
this(source.readLong(), source.createByteArray());
}
/** @hide */
@TestApi
public SecurityEvent(long id, byte[] data) {
mId = id;
mEvent = Event.fromBytes(data);
}
/**
* Returns the timestamp in nano seconds when this event was logged.
*/
public long getTimeNanos() {
return mEvent.getTimeNanos();
}
/**
* Returns the tag of this log entry, which specifies entry's semantics.
*/
public @SecurityLogTag int getTag() {
return mEvent.getTag();
}
/**
* Returns the payload contained in this log entry or {@code null} if there is no payload.
*/
public Object getData() {
return mEvent.getData();
}
/** @hide */
public int getIntegerData(int index) {
return (Integer) ((Object[]) mEvent.getData())[index];
}
/** @hide */
public String getStringData(int index) {
return (String) ((Object[]) mEvent.getData())[index];
}
/**
* @hide
*/
public void setId(long id) {
this.mId = id;
}
/**
* Returns the id of the event, where the id monotonically increases for each event. The id
* is reset when the device reboots, and when security logging is enabled.
*/
public long getId() {
return mId;
}
/**
* Returns severity level for the event.
*/
public @SecurityLogLevel int getLogLevel() {
switch (getTag()) {
case TAG_ADB_SHELL_INTERACTIVE:
case TAG_ADB_SHELL_CMD:
case TAG_SYNC_RECV_FILE:
case TAG_SYNC_SEND_FILE:
case TAG_APP_PROCESS_START:
case TAG_KEYGUARD_DISMISSED:
case TAG_KEYGUARD_SECURED:
case TAG_OS_STARTUP:
case TAG_OS_SHUTDOWN:
case TAG_LOGGING_STARTED:
case TAG_LOGGING_STOPPED:
case TAG_MEDIA_MOUNT:
case TAG_MEDIA_UNMOUNT:
case TAG_PASSWORD_EXPIRATION_SET:
case TAG_PASSWORD_COMPLEXITY_SET:
case TAG_PASSWORD_HISTORY_LENGTH_SET:
case TAG_MAX_SCREEN_LOCK_TIMEOUT_SET:
case TAG_MAX_PASSWORD_ATTEMPTS_SET:
case TAG_USER_RESTRICTION_ADDED:
case TAG_USER_RESTRICTION_REMOVED:
case TAG_CAMERA_POLICY_SET:
return LEVEL_INFO;
case TAG_CERT_AUTHORITY_REMOVED:
case TAG_CRYPTO_SELF_TEST_COMPLETED:
return getSuccess() ? LEVEL_INFO : LEVEL_ERROR;
case TAG_CERT_AUTHORITY_INSTALLED:
case TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT:
case TAG_KEY_IMPORT:
case TAG_KEY_DESTRUCTION:
case TAG_KEY_GENERATED:
return getSuccess() ? LEVEL_INFO : LEVEL_WARNING;
case TAG_LOG_BUFFER_SIZE_CRITICAL:
case TAG_WIPE_FAILURE:
case TAG_KEY_INTEGRITY_VIOLATION:
return LEVEL_ERROR;
case TAG_CERT_VALIDATION_FAILURE:
return LEVEL_WARNING;
default:
return LEVEL_INFO;
}
}
// Success/failure if present is encoded as an integer in the first (0th) element of data.
private boolean getSuccess() {
final Object data = getData();
if (data == null || !(data instanceof Object[])) {
return false;
}
final Object[] array = (Object[]) data;
return array.length >= 1 && array[0] instanceof Integer && (Integer) array[0] != 0;
}
/**
* Returns a copy of the security event suitable to be consumed by the provided user.
* This method will either return the original event itself if the event does not contain
* any sensitive data; or a copy of itself but with sensitive information redacted; or
* {@code null} if the entire event should not be accessed by the given user.
*
* @param accessingUser which user this security event is to be accessed, must be a
* concrete user id.
* @hide
*/
public SecurityEvent redact(int accessingUser) {
// Which user the event is associated with, for the purpose of log redaction.
final int userId;
switch (getTag()) {
case SecurityLog.TAG_ADB_SHELL_CMD:
return new SecurityEvent(getId(), mEvent.withNewData("").getBytes());
case SecurityLog.TAG_MEDIA_MOUNT:
case SecurityLog.TAG_MEDIA_UNMOUNT:
// Partial redaction
String mountPoint;
try {
mountPoint = getStringData(0);
} catch (Exception e) {
return null;
}
return new SecurityEvent(getId(),
mEvent.withNewData(new Object[] {mountPoint, ""}).getBytes());
case SecurityLog.TAG_APP_PROCESS_START:
try {
userId = UserHandle.getUserId(getIntegerData(2));
} catch (Exception e) {
return null;
}
break;
case SecurityLog.TAG_CERT_AUTHORITY_INSTALLED:
case SecurityLog.TAG_CERT_AUTHORITY_REMOVED:
try {
userId = getIntegerData(2);
} catch (Exception e) {
return null;
}
break;
case SecurityLog.TAG_KEY_GENERATED:
case SecurityLog.TAG_KEY_IMPORT:
case SecurityLog.TAG_KEY_DESTRUCTION:
try {
userId = UserHandle.getUserId(getIntegerData(2));
} catch (Exception e) {
return null;
}
break;
case SecurityLog.TAG_KEY_INTEGRITY_VIOLATION:
try {
userId = UserHandle.getUserId(getIntegerData(1));
} catch (Exception e) {
return null;
}
break;
default:
userId = UserHandle.USER_NULL;
}
// If the event is not user-specific, or matches the accessing user, return it
// unmodified, else redact by returning null
if (userId == UserHandle.USER_NULL || accessingUser == userId) {
return this;
} else {
return null;
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mId);
dest.writeByteArray(mEvent.getBytes());
}
public static final @android.annotation.NonNull Parcelable.Creator<SecurityEvent> CREATOR =
new Parcelable.Creator<SecurityEvent>() {
@Override
public SecurityEvent createFromParcel(Parcel source) {
return new SecurityEvent(source);
}
@Override
public SecurityEvent[] newArray(int size) {
return new SecurityEvent[size];
}
};
/**
* @hide
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SecurityEvent other = (SecurityEvent) o;
return mEvent.equals(other.mEvent) && mId == other.mId;
}
/**
* @hide
*/
@Override
public int hashCode() {
return Objects.hash(mEvent, mId);
}
/** @hide */
public boolean eventEquals(SecurityEvent other) {
return other != null && mEvent.equals(other.mEvent);
}
}
/**
* Redacts events in-place according to which user will consume the events.
*
* @param accessingUser which user will consume the redacted events, or UserHandle.USER_ALL if
* redaction should be skipped.
* @hide
*/
public static void redactEvents(ArrayList<SecurityEvent> logList, int accessingUser) {
if (accessingUser == UserHandle.USER_ALL) return;
int end = 0;
for (int i = 0; i < logList.size(); i++) {
SecurityEvent event = logList.get(i);
event = event.redact(accessingUser);
if (event != null) {
logList.set(end, event);
end++;
}
}
for (int i = logList.size() - 1; i >= end; i--) {
logList.remove(i);
}
}
/**
* Retrieve all security logs and return immediately.
* @hide
*/
public static native void readEvents(Collection<SecurityEvent> output) throws IOException;
/**
* Retrieve all security logs since the given timestamp in nanoseconds and return immediately.
* @hide
*/
public static native void readEventsSince(long timestamp, Collection<SecurityEvent> output)
throws IOException;
/**
* Retrieve all security logs before the last reboot. May return corrupted data due to
* unreliable pstore.
* @hide
*/
public static native void readPreviousEvents(Collection<SecurityEvent> output)
throws IOException;
/**
* Retrieve all security logs whose timestamp is equal to or greater than the given timestamp in
* nanoseconds. This method will block until either the last log earlier than the given
* timestamp is about to be pruned, or after a 2-hour timeout has passed.
* @hide
*/
public static native void readEventsOnWrapping(long timestamp, Collection<SecurityEvent> output)
throws IOException;
/**
* Write a log entry to the underlying storage, with a string payload.
* @hide
*/
public static native int writeEvent(int tag, String str);
/**
* Write a log entry to the underlying storage, with several payloads.
* Supported types of payload are: integer, long, float, string plus array of supported types.
* @hide
*/
public static native int writeEvent(int tag, Object... payloads);
}