1 /*
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 
17 package android.app.admin;
18 
19 import android.annotation.IntDef;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 import android.os.SystemProperties;
23 import android.util.EventLog.Event;
24 
25 import java.io.IOException;
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 import java.util.Collection;
29 
30 /**
31  * Definitions for working with security logs.
32  *
33  * <p>Device owner apps can control the logging with
34  * {@link DevicePolicyManager#setSecurityLoggingEnabled}. When security logs are enabled, device
35  * owner apps receive periodic callbacks from {@link DeviceAdminReceiver#onSecurityLogsAvailable},
36  * at which time new batch of logs can be collected via
37  * {@link DevicePolicyManager#retrieveSecurityLogs}. {@link SecurityEvent} describes the type and
38  * format of security logs being collected.
39  */
40 public class SecurityLog {
41 
42     private static final String PROPERTY_LOGGING_ENABLED = "persist.logd.security";
43 
44     /** @hide */
45     @Retention(RetentionPolicy.SOURCE)
46     @IntDef({TAG_ADB_SHELL_INTERACTIVE, TAG_ADB_SHELL_CMD, TAG_SYNC_RECV_FILE, TAG_SYNC_SEND_FILE,
47         TAG_APP_PROCESS_START, TAG_KEYGUARD_DISMISSED, TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT,
48         TAG_KEYGUARD_SECURED})
49     public @interface SECURITY_LOG_TAG {}
50 
51     /**
52      * Indicate that an ADB interactive shell was opened via "adb shell".
53      * There is no extra payload in the log event.
54      */
55     public static final int TAG_ADB_SHELL_INTERACTIVE =
56             SecurityLogTags.SECURITY_ADB_SHELL_INTERACTIVE;
57     /**
58      * Indicate that an shell command was issued over ADB via "adb shell command"
59      * The log entry contains a string data of the shell command, accessible via
60      * {@link SecurityEvent#getData()}
61      */
62     public static final int TAG_ADB_SHELL_CMD = SecurityLogTags.SECURITY_ADB_SHELL_COMMAND;
63     /**
64      * Indicate that a file was pulled from the device via the adb daemon, for example via
65      * "adb pull". The log entry contains a string data of the path of the pulled file,
66      * accessible via {@link SecurityEvent#getData()}
67      */
68     public static final int TAG_SYNC_RECV_FILE = SecurityLogTags.SECURITY_ADB_SYNC_RECV;
69     /**
70      * Indicate that a file was pushed to the device via the adb daemon, for example via
71      * "adb push". The log entry contains a string data of the destination path of the
72      * pushed file, accessible via {@link SecurityEvent#getData()}
73      */
74     public static final int TAG_SYNC_SEND_FILE = SecurityLogTags.SECURITY_ADB_SYNC_SEND;
75     /**
76      * Indicate that an app process was started. The log entry contains the following
77      * information about the process encapsulated in an {@link Object} array, accessible via
78      * {@link SecurityEvent#getData()}:
79      * process name (String), exact start time (long), app Uid (integer), app Pid (integer),
80      * seinfo tag (String), SHA-256 hash of the base APK in hexadecimal (String)
81      */
82     public static final int TAG_APP_PROCESS_START = SecurityLogTags.SECURITY_APP_PROCESS_START;
83     /**
84      * Indicate that keyguard is being dismissed.
85      * There is no extra payload in the log event.
86      */
87     public static final int TAG_KEYGUARD_DISMISSED =
88             SecurityLogTags.SECURITY_KEYGUARD_DISMISSED;
89     /**
90      * Indicate that there has been an authentication attempt to dismiss the keyguard. The log entry
91      * contains the following information about the attempt encapsulated in an {@link Object} array,
92      * accessible via {@link SecurityEvent#getData()}:
93      * attempt result (integer, 1 for successful, 0 for unsuccessful), strength of auth method
94      * (integer, 1 if strong auth method was used, 0 otherwise)
95      */
96     public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT =
97             SecurityLogTags.SECURITY_KEYGUARD_DISMISS_AUTH_ATTEMPT;
98     /**
99      * Indicate that the device has been locked, either by user or by timeout.
100      * There is no extra payload in the log event.
101      */
102     public static final int TAG_KEYGUARD_SECURED = SecurityLogTags.SECURITY_KEYGUARD_SECURED;
103 
104     /**
105      * Returns if security logging is enabled. Log producers should only write new logs if this is
106      * true. Under the hood this is the logical AND of whether device owner exists and whether
107      * it enables logging by setting the system property {@link #PROPERTY_LOGGING_ENABLED}.
108      * @hide
109      */
isLoggingEnabled()110     public static native boolean isLoggingEnabled();
111 
112     /**
113      * @hide
114      */
setLoggingEnabledProperty(boolean enabled)115     public static void setLoggingEnabledProperty(boolean enabled) {
116         SystemProperties.set(PROPERTY_LOGGING_ENABLED, enabled ? "true" : "false");
117     }
118 
119     /**
120      * @hide
121      */
getLoggingEnabledProperty()122     public static boolean getLoggingEnabledProperty() {
123         return SystemProperties.getBoolean(PROPERTY_LOGGING_ENABLED, false);
124     }
125 
126     /**
127      * A class representing a security event log entry.
128      */
129     public static final class SecurityEvent implements Parcelable {
130         private Event mEvent;
131 
132         /** @hide */
SecurityEvent(byte[] data)133         /*package*/ SecurityEvent(byte[] data) {
134             mEvent = Event.fromBytes(data);
135         }
136 
137         /**
138          * Returns the timestamp in nano seconds when this event was logged.
139          */
getTimeNanos()140         public long getTimeNanos() {
141             return mEvent.getTimeNanos();
142         }
143 
144         /**
145          * Returns the tag of this log entry, which specifies entry's semantics.
146          * Could be one of {@link SecurityLog#TAG_SYNC_RECV_FILE},
147          * {@link SecurityLog#TAG_SYNC_SEND_FILE}, {@link SecurityLog#TAG_ADB_SHELL_CMD},
148          * {@link SecurityLog#TAG_ADB_SHELL_INTERACTIVE}, {@link SecurityLog#TAG_APP_PROCESS_START},
149          * {@link SecurityLog#TAG_KEYGUARD_DISMISSED}, {@link SecurityLog#TAG_KEYGUARD_SECURED},
150          * {@link SecurityLog#TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT}.
151          */
getTag()152         public @SECURITY_LOG_TAG int getTag() {
153             return mEvent.getTag();
154         }
155 
156         /**
157          * Returns the payload contained in this log entry or {@code null} if there is no payload.
158          */
getData()159         public Object getData() {
160             return mEvent.getData();
161         }
162 
163         @Override
describeContents()164         public int describeContents() {
165             return 0;
166         }
167 
168         @Override
writeToParcel(Parcel dest, int flags)169         public void writeToParcel(Parcel dest, int flags) {
170             dest.writeByteArray(mEvent.getBytes());
171         }
172 
173         public static final Parcelable.Creator<SecurityEvent> CREATOR =
174                 new Parcelable.Creator<SecurityEvent>() {
175             @Override
176             public SecurityEvent createFromParcel(Parcel source) {
177                 return new SecurityEvent(source.createByteArray());
178             }
179 
180             @Override
181             public SecurityEvent[] newArray(int size) {
182                 return new SecurityEvent[size];
183             }
184         };
185 
186         /**
187          * @hide
188          */
189         @Override
equals(Object o)190         public boolean equals(Object o) {
191             if (this == o) return true;
192             if (o == null || getClass() != o.getClass()) return false;
193             SecurityEvent other = (SecurityEvent) o;
194             return mEvent.equals(other.mEvent);
195         }
196 
197         /**
198          * @hide
199          */
200         @Override
hashCode()201         public int hashCode() {
202             return mEvent.hashCode();
203         }
204     }
205     /**
206      * Retrieve all security logs and return immediately.
207      * @hide
208      */
readEvents(Collection<SecurityEvent> output)209     public static native void readEvents(Collection<SecurityEvent> output) throws IOException;
210 
211     /**
212      * Retrieve all security logs since the given timestamp in nanoseconds and return immediately.
213      * @hide
214      */
readEventsSince(long timestamp, Collection<SecurityEvent> output)215     public static native void readEventsSince(long timestamp, Collection<SecurityEvent> output)
216             throws IOException;
217 
218     /**
219      * Retrieve all security logs before the last reboot. May return corrupted data due to
220      * unreliable pstore.
221      * @hide
222      */
readPreviousEvents(Collection<SecurityEvent> output)223     public static native void readPreviousEvents(Collection<SecurityEvent> output)
224             throws IOException;
225 
226     /**
227      * Retrieve all security logs whose timestamp (in nanosceonds) is equal to or greater than the
228      * given timestamp. This method will block until either the last log earlier than the given
229      * timestamp is about to be pruned, or after a 2-hour timeout has passed.
230      * @hide
231      */
readEventsOnWrapping(long timestamp, Collection<SecurityEvent> output)232     public static native void readEventsOnWrapping(long timestamp, Collection<SecurityEvent> output)
233             throws IOException;
234 
235     /**
236      * Write a log entry to the underlying storage, with a string payload.
237      * @hide
238      */
writeEvent(int tag, String str)239     public static native int writeEvent(int tag, String str);
240 
241     /**
242      * Write a log entry to the underlying storage, with several payloads.
243      * Supported types of payload are: integer, long, float, string plus array of supported types.
244      * @hide
245      */
writeEvent(int tag, Object... payloads)246     public static native int writeEvent(int tag, Object... payloads);
247 }
248