• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 dalvik.system;
18 
19 import libcore.util.NonNull;
20 
21 import java.util.Objects;
22 import java.util.zip.ZipException;
23 
24 /**
25  * Enables validation of zip file entry paths to prevent exploitation of the path traversal
26  * vulnerability, e.g. zip path entries containing ".." or "/". For more details, read
27  * <a href="https://developer.android.com/topic/security/risks/zip-path-traversal">this</a>.
28  * <p>
29  * The default implementation accepts all zip file entry paths without raising any exceptions.
30  * <p>
31  * For custom validation rules, the core functionality should be implemented in a {@link Callback}
32  * interface and that instance should be set in {@link #setCallback(Callback)}.
33  * <p>
34  * Existing validation could be set to a default one by calling {@link #clearCallback()}.
35  */
36 public final class ZipPathValidator {
37 
38     /**
39      * Default implementation of the {@link Callback} interface which accepts all paths.
40      *
41      * @hide
42      */
43     public static final Callback DEFAULT = new Callback() {};
44 
45     private static volatile Callback sInstance = DEFAULT;
46 
47     /**
48      * Clears the current validation mechanism by setting the current callback instance to a default
49      * validation.
50      */
clearCallback()51     public static void clearCallback() {
52         sInstance = DEFAULT;
53     }
54 
55     /**
56      * Sets the current callback implementation for zip paths.
57      * <p>
58      * The provided callback should not perform IO or any blocking operations, but only perform path
59      * validation. A typical implementation will validate String entries in a single pass and throw
60      * a {@link ZipException} if the path contains potentially hazardous components such as "..".
61      *
62      * @param callback An instance of {@link Callback}'s implementation.
63      */
setCallback(@onNull Callback callback)64     public static void setCallback(@NonNull Callback callback) {
65         sInstance = Objects.requireNonNull(callback);
66     }
67 
68     /**
69      * Retrieves the current validator set by {@link #setCallback(Callback)}.
70      *
71      * @return Current callback.
72      *
73      * @hide
74      */
getInstance()75     public static @NonNull Callback getInstance() {
76         return sInstance;
77     }
78 
79     /**
80      * Returns true if the current validator is the default implementation {@link DEFAULT},
81      * otherwise false.
82      *
83      * @hide
84      */
isClear()85     public static boolean isClear() {
86         return sInstance.equals(DEFAULT);
87     }
88 
89     /**
90      * Interface that defines the core validation mechanism when accessing zip file entry paths.
91      */
92     public interface Callback {
93         /**
94          * Called to check the validity of the path of a zip entry. The default implementation
95          * accepts all paths without raising any exceptions.
96          * <p>
97          * This method will be called by {@link java.util.zip.ZipInputStream#getNextEntry} or
98          * {@link java.util.zip.ZipFile#ZipFile(String)}.
99          *
100          * @param path The name of the zip entry.
101          * @throws ZipException If the zip entry is invalid depending on the implementation.
102          */
onZipEntryAccess(@onNull String path)103         default void onZipEntryAccess(@NonNull String path) throws ZipException {}
104     }
105 
ZipPathValidator()106     private ZipPathValidator() {}
107 }
108