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