blob: d3b66d0d144a06d6059f30d9215c5bd1399b2697 [file] [log] [blame]
Rubin Xu75431fb2016-01-07 21:12:14 +00001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Michal Karpinski6235a942016-03-15 12:07:23 +000017package android.app.admin;
Rubin Xu75431fb2016-01-07 21:12:14 +000018
19import android.annotation.IntDef;
Naomi Musgravedb980f42017-11-28 10:56:47 +000020import android.annotation.TestApi;
Rubin Xu75431fb2016-01-07 21:12:14 +000021import android.os.Parcel;
22import android.os.Parcelable;
23import android.os.SystemProperties;
24import android.util.EventLog.Event;
25
26import java.io.IOException;
27import java.lang.annotation.Retention;
28import java.lang.annotation.RetentionPolicy;
29import java.util.Collection;
Naomi Musgravedb980f42017-11-28 10:56:47 +000030import java.util.Objects;
Rubin Xu75431fb2016-01-07 21:12:14 +000031
Pavel Grafov73f747b2017-04-10 19:29:41 +010032/**
33 * Definitions for working with security logs.
34 *
35 * <p>Device owner apps can control the logging with
36 * {@link DevicePolicyManager#setSecurityLoggingEnabled}. When security logs are enabled, device
37 * owner apps receive periodic callbacks from {@link DeviceAdminReceiver#onSecurityLogsAvailable},
38 * at which time new batch of logs can be collected via
39 * {@link DevicePolicyManager#retrieveSecurityLogs}. {@link SecurityEvent} describes the type and
40 * format of security logs being collected.
41 */
Rubin Xu75431fb2016-01-07 21:12:14 +000042public class SecurityLog {
43
44 private static final String PROPERTY_LOGGING_ENABLED = "persist.logd.security";
45
46 /** @hide */
47 @Retention(RetentionPolicy.SOURCE)
Jeff Sharkeyce8db992017-12-13 20:05:05 -070048 @IntDef(prefix = { "TAG_" }, value = {
49 TAG_ADB_SHELL_INTERACTIVE,
50 TAG_ADB_SHELL_CMD,
51 TAG_SYNC_RECV_FILE,
52 TAG_SYNC_SEND_FILE,
53 TAG_APP_PROCESS_START,
54 TAG_KEYGUARD_DISMISSED,
55 TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT,
56 TAG_KEYGUARD_SECURED
57 })
58 public @interface SecurityLogTag {}
Rubin Xu75431fb2016-01-07 21:12:14 +000059
60 /**
61 * Indicate that an ADB interactive shell was opened via "adb shell".
62 * There is no extra payload in the log event.
63 */
64 public static final int TAG_ADB_SHELL_INTERACTIVE =
65 SecurityLogTags.SECURITY_ADB_SHELL_INTERACTIVE;
66 /**
67 * Indicate that an shell command was issued over ADB via "adb shell command"
68 * The log entry contains a string data of the shell command, accessible via
69 * {@link SecurityEvent#getData()}
70 */
71 public static final int TAG_ADB_SHELL_CMD = SecurityLogTags.SECURITY_ADB_SHELL_COMMAND;
72 /**
73 * Indicate that a file was pulled from the device via the adb daemon, for example via
74 * "adb pull". The log entry contains a string data of the path of the pulled file,
75 * accessible via {@link SecurityEvent#getData()}
76 */
77 public static final int TAG_SYNC_RECV_FILE = SecurityLogTags.SECURITY_ADB_SYNC_RECV;
78 /**
79 * Indicate that a file was pushed to the device via the adb daemon, for example via
80 * "adb push". The log entry contains a string data of the destination path of the
81 * pushed file, accessible via {@link SecurityEvent#getData()}
82 */
83 public static final int TAG_SYNC_SEND_FILE = SecurityLogTags.SECURITY_ADB_SYNC_SEND;
84 /**
85 * Indicate that an app process was started. The log entry contains the following
Rubin Xu232990d2016-02-18 15:55:21 +000086 * information about the process encapsulated in an {@link Object} array, accessible via
87 * {@link SecurityEvent#getData()}:
Rubin Xu75431fb2016-01-07 21:12:14 +000088 * process name (String), exact start time (long), app Uid (integer), app Pid (integer),
Michal Karpinskie0e100982016-03-30 15:02:26 +010089 * seinfo tag (String), SHA-256 hash of the base APK in hexadecimal (String)
Rubin Xu75431fb2016-01-07 21:12:14 +000090 */
91 public static final int TAG_APP_PROCESS_START = SecurityLogTags.SECURITY_APP_PROCESS_START;
Rubin Xu75431fb2016-01-07 21:12:14 +000092 /**
Michal Karpinski31502d32016-01-25 16:43:07 +000093 * Indicate that keyguard is being dismissed.
94 * There is no extra payload in the log event.
Rubin Xu75431fb2016-01-07 21:12:14 +000095 */
Michal Karpinski31502d32016-01-25 16:43:07 +000096 public static final int TAG_KEYGUARD_DISMISSED =
97 SecurityLogTags.SECURITY_KEYGUARD_DISMISSED;
98 /**
99 * Indicate that there has been an authentication attempt to dismiss the keyguard. The log entry
Rubin Xu232990d2016-02-18 15:55:21 +0000100 * contains the following information about the attempt encapsulated in an {@link Object} array,
101 * accessible via {@link SecurityEvent#getData()}:
102 * attempt result (integer, 1 for successful, 0 for unsuccessful), strength of auth method
103 * (integer, 1 if strong auth method was used, 0 otherwise)
Michal Karpinski31502d32016-01-25 16:43:07 +0000104 */
105 public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT =
106 SecurityLogTags.SECURITY_KEYGUARD_DISMISS_AUTH_ATTEMPT;
Rubin Xu75431fb2016-01-07 21:12:14 +0000107 /**
108 * Indicate that the device has been locked, either by user or by timeout.
Michal Karpinski31502d32016-01-25 16:43:07 +0000109 * There is no extra payload in the log event.
Rubin Xu75431fb2016-01-07 21:12:14 +0000110 */
Michal Karpinski31502d32016-01-25 16:43:07 +0000111 public static final int TAG_KEYGUARD_SECURED = SecurityLogTags.SECURITY_KEYGUARD_SECURED;
Rubin Xu75431fb2016-01-07 21:12:14 +0000112
113 /**
Michal Karpinski6235a942016-03-15 12:07:23 +0000114 * Returns if security logging is enabled. Log producers should only write new logs if this is
Rubin Xu75431fb2016-01-07 21:12:14 +0000115 * true. Under the hood this is the logical AND of whether device owner exists and whether
116 * it enables logging by setting the system property {@link #PROPERTY_LOGGING_ENABLED}.
117 * @hide
118 */
119 public static native boolean isLoggingEnabled();
120
121 /**
122 * @hide
123 */
124 public static void setLoggingEnabledProperty(boolean enabled) {
125 SystemProperties.set(PROPERTY_LOGGING_ENABLED, enabled ? "true" : "false");
126 }
127
128 /**
129 * @hide
130 */
131 public static boolean getLoggingEnabledProperty() {
132 return SystemProperties.getBoolean(PROPERTY_LOGGING_ENABLED, false);
133 }
134
135 /**
136 * A class representing a security event log entry.
137 */
Jeff Sharkey50d1c042016-02-29 16:34:46 -0700138 public static final class SecurityEvent implements Parcelable {
Rubin Xu75431fb2016-01-07 21:12:14 +0000139 private Event mEvent;
Naomi Musgravedb980f42017-11-28 10:56:47 +0000140 private long mId;
141
142 /**
143 * Constructor used by native classes to generate SecurityEvent instances.
144 * @hide
145 */
146 /* package */ SecurityEvent(byte[] data) {
147 this(0, data);
148 }
149
150 /**
151 * Constructor used by Parcelable.Creator to generate SecurityEvent instances.
152 * @hide
153 */
154 /* package */ SecurityEvent(Parcel source) {
155 this(source.readLong(), source.createByteArray());
156 }
Rubin Xu75431fb2016-01-07 21:12:14 +0000157
158 /** @hide */
Naomi Musgravedb980f42017-11-28 10:56:47 +0000159 @TestApi
160 public SecurityEvent(long id, byte[] data) {
161 mId = id;
Rubin Xu75431fb2016-01-07 21:12:14 +0000162 mEvent = Event.fromBytes(data);
163 }
164
165 /**
166 * Returns the timestamp in nano seconds when this event was logged.
167 */
168 public long getTimeNanos() {
169 return mEvent.getTimeNanos();
170 }
171
172 /**
173 * Returns the tag of this log entry, which specifies entry's semantics.
Rubin Xu75431fb2016-01-07 21:12:14 +0000174 */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700175 public @SecurityLogTag int getTag() {
Rubin Xu75431fb2016-01-07 21:12:14 +0000176 return mEvent.getTag();
177 }
178
179 /**
Pavel Grafov739cda82017-02-02 12:41:20 +0000180 * Returns the payload contained in this log entry or {@code null} if there is no payload.
Rubin Xu75431fb2016-01-07 21:12:14 +0000181 */
182 public Object getData() {
183 return mEvent.getData();
184 }
185
Naomi Musgravedb980f42017-11-28 10:56:47 +0000186 /**
187 * @hide
188 */
189 public void setId(long id) {
190 this.mId = id;
191 }
192
193 /**
194 * Returns the id of the event, where the id monotonically increases for each event. The id
195 * is reset when the device reboots, and when security logging is enabled.
196 */
197 public long getId() {
198 return mId;
199 }
200
Rubin Xu75431fb2016-01-07 21:12:14 +0000201 @Override
202 public int describeContents() {
203 return 0;
204 }
205
206 @Override
207 public void writeToParcel(Parcel dest, int flags) {
Naomi Musgravedb980f42017-11-28 10:56:47 +0000208 dest.writeLong(mId);
Rubin Xu75431fb2016-01-07 21:12:14 +0000209 dest.writeByteArray(mEvent.getBytes());
210 }
211
212 public static final Parcelable.Creator<SecurityEvent> CREATOR =
213 new Parcelable.Creator<SecurityEvent>() {
214 @Override
215 public SecurityEvent createFromParcel(Parcel source) {
Naomi Musgravedb980f42017-11-28 10:56:47 +0000216 return new SecurityEvent(source);
Rubin Xu75431fb2016-01-07 21:12:14 +0000217 }
218
219 @Override
220 public SecurityEvent[] newArray(int size) {
221 return new SecurityEvent[size];
222 }
223 };
Pavel Grafov4ce59d42017-02-25 19:45:43 +0000224
225 /**
226 * @hide
227 */
228 @Override
229 public boolean equals(Object o) {
230 if (this == o) return true;
231 if (o == null || getClass() != o.getClass()) return false;
232 SecurityEvent other = (SecurityEvent) o;
Naomi Musgravedb980f42017-11-28 10:56:47 +0000233 return mEvent.equals(other.mEvent) && mId == other.mId;
Pavel Grafov4ce59d42017-02-25 19:45:43 +0000234 }
235
236 /**
237 * @hide
238 */
239 @Override
240 public int hashCode() {
Naomi Musgravedb980f42017-11-28 10:56:47 +0000241 return Objects.hash(mEvent, mId);
Pavel Grafov4ce59d42017-02-25 19:45:43 +0000242 }
Rubin Xu75431fb2016-01-07 21:12:14 +0000243 }
244 /**
245 * Retrieve all security logs and return immediately.
246 * @hide
247 */
248 public static native void readEvents(Collection<SecurityEvent> output) throws IOException;
249
250 /**
251 * Retrieve all security logs since the given timestamp in nanoseconds and return immediately.
252 * @hide
253 */
254 public static native void readEventsSince(long timestamp, Collection<SecurityEvent> output)
255 throws IOException;
256
257 /**
258 * Retrieve all security logs before the last reboot. May return corrupted data due to
259 * unreliable pstore.
260 * @hide
261 */
262 public static native void readPreviousEvents(Collection<SecurityEvent> output)
263 throws IOException;
264
265 /**
266 * Retrieve all security logs whose timestamp (in nanosceonds) is equal to or greater than the
267 * given timestamp. This method will block until either the last log earlier than the given
268 * timestamp is about to be pruned, or after a 2-hour timeout has passed.
269 * @hide
270 */
271 public static native void readEventsOnWrapping(long timestamp, Collection<SecurityEvent> output)
272 throws IOException;
273
274 /**
275 * Write a log entry to the underlying storage, with a string payload.
276 * @hide
277 */
278 public static native int writeEvent(int tag, String str);
279
280 /**
281 * Write a log entry to the underlying storage, with several payloads.
282 * Supported types of payload are: integer, long, float, string plus array of supported types.
283 * @hide
284 */
285 public static native int writeEvent(int tag, Object... payloads);
286}