blob: 47c7e56febe09d56d9a278bf08a67725976572ce [file] [log] [blame]
Song Panc56a78d2020-01-02 16:06:11 +00001/*
2 * Copyright (C) 2020 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
17package com.android.server.integrity;
18
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +000019import static com.google.common.truth.Truth.assertThat;
Song Panc56a78d2020-01-02 16:06:11 +000020
21import android.content.integrity.AppInstallMetadata;
22import android.content.integrity.AtomicFormula;
23import android.content.integrity.AtomicFormula.IntAtomicFormula;
24import android.content.integrity.AtomicFormula.StringAtomicFormula;
25import android.content.integrity.CompoundFormula;
26import android.content.integrity.Rule;
27import android.util.Slog;
28
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +000029import com.android.server.integrity.parser.RuleBinaryParser;
30import com.android.server.integrity.serializer.RuleBinarySerializer;
Song Panc56a78d2020-01-02 16:06:11 +000031
32import org.junit.After;
33import org.junit.Before;
34import org.junit.Test;
35import org.junit.runner.RunWith;
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +000036import org.junit.runners.JUnit4;
Song Panc56a78d2020-01-02 16:06:11 +000037
38import java.io.File;
39import java.nio.file.Files;
40import java.nio.file.Path;
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +000041import java.util.ArrayList;
Song Panc56a78d2020-01-02 16:06:11 +000042import java.util.Arrays;
43import java.util.Collections;
44import java.util.Comparator;
45import java.util.List;
46
47/** Unit test for {@link IntegrityFileManager} */
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +000048@RunWith(JUnit4.class)
Song Panc56a78d2020-01-02 16:06:11 +000049public class IntegrityFileManagerTest {
50 private static final String TAG = "IntegrityFileManagerTest";
51
52 private static final String VERSION = "version";
53 private static final String RULE_PROVIDER = "rule_provider";
54
55 private File mTmpDir;
56
57 // under test
58 private IntegrityFileManager mIntegrityFileManager;
59
60 @Before
61 public void setUp() throws Exception {
62 mTmpDir = Files.createTempDirectory("IntegrityFileManagerTest").toFile();
63 Slog.i(TAG, "Using temp directory " + mTmpDir);
64
65 // Use Xml Parser/Serializer to help with debugging since we can just print the file.
66 mIntegrityFileManager =
67 new IntegrityFileManager(
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +000068 new RuleBinaryParser(), new RuleBinarySerializer(), mTmpDir);
Song Panc56a78d2020-01-02 16:06:11 +000069 Files.walk(mTmpDir.toPath())
70 .forEach(
71 path -> {
72 Slog.i(TAG, "before " + path);
73 });
74 }
75
76 @After
77 public void tearDown() throws Exception {
78 Files.walk(mTmpDir.toPath())
79 .forEach(
80 path -> {
81 Slog.i(TAG, "after " + path);
82 });
83 // Sorting paths in reverse order guarantees that we delete inside files before deleting
84 // directory.
85 Files.walk(mTmpDir.toPath())
86 .sorted(Comparator.reverseOrder())
87 .map(Path::toFile)
88 .forEach(File::delete);
89 }
90
91 @Test
92 public void testGetMetadata() throws Exception {
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +000093 assertThat(mIntegrityFileManager.readMetadata()).isNull();
Song Panc56a78d2020-01-02 16:06:11 +000094 mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
95
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +000096 assertThat(mIntegrityFileManager.readMetadata()).isNotNull();
97 assertThat(mIntegrityFileManager.readMetadata().getVersion()).isEqualTo(VERSION);
98 assertThat(mIntegrityFileManager.readMetadata().getRuleProvider()).isEqualTo(RULE_PROVIDER);
99 }
100
101 @Test
102 public void testIsInitialized() throws Exception {
103 assertThat(mIntegrityFileManager.initialized()).isFalse();
104 mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
105 assertThat(mIntegrityFileManager.initialized()).isTrue();
Song Panc56a78d2020-01-02 16:06:11 +0000106 }
107
108 @Test
109 public void testGetRules() throws Exception {
110 String packageName = "package";
111 String packageCert = "cert";
112 int version = 123;
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +0000113 Rule packageNameRule = getPackageNameIndexedRule(packageName);
114 Rule packageCertRule = getAppCertificateIndexedRule(packageCert);
Song Panc56a78d2020-01-02 16:06:11 +0000115 Rule versionCodeRule =
116 new Rule(
117 new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, version),
118 Rule.DENY);
119 Rule randomRule =
120 new Rule(
121 new CompoundFormula(
122 CompoundFormula.OR,
123 Arrays.asList(
124 new StringAtomicFormula(
125 AtomicFormula.PACKAGE_NAME,
126 "abc",
127 /* isHashedValue= */ false),
128 new IntAtomicFormula(
129 AtomicFormula.VERSION_CODE,
130 AtomicFormula.LE,
131 version))),
132 Rule.DENY);
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +0000133
Song Panc56a78d2020-01-02 16:06:11 +0000134 List<Rule> rules =
135 Arrays.asList(packageNameRule, packageCertRule, versionCodeRule, randomRule);
136 mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, rules);
137
Song Pan95de69d2020-01-10 12:29:35 +0000138 AppInstallMetadata appInstallMetadata =
139 new AppInstallMetadata.Builder()
140 .setPackageName(packageName)
141 .setAppCertificate(packageCert)
142 .setVersionCode(version)
143 .setInstallerName("abc")
144 .setInstallerCertificate("abc")
145 .setIsPreInstalled(true)
146 .build();
Song Panc56a78d2020-01-02 16:06:11 +0000147 List<Rule> rulesFetched = mIntegrityFileManager.readRules(appInstallMetadata);
148
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +0000149 assertThat(rulesFetched)
150 .containsExactly(packageNameRule, packageCertRule, versionCodeRule, randomRule);
Song Panc56a78d2020-01-02 16:06:11 +0000151 }
152
153 @Test
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +0000154 public void testGetRules_indexedForManyRules() throws Exception {
155 String packageName = "package";
156 String installerName = "installer";
157 String appCertificate = "cert";
158
159 // Create a rule set with 2500 package name indexed, 2500 app certificate indexed and
160 // 500 unindexed rules.
161 List<Rule> rules = new ArrayList<>();
162
163 for (int i = 0; i < 2500; i++) {
164 rules.add(getPackageNameIndexedRule(String.format("%s%04d", packageName, i)));
165 rules.add(getAppCertificateIndexedRule(String.format("%s%04d", appCertificate, i)));
166 }
167
168 for (int i = 0; i < 70; i++) {
169 rules.add(getInstallerCertificateRule(String.format("%s%04d", installerName, i)));
170 }
171
172 // Write the rules and get them indexed.
173 mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, rules);
174
175 // Read the rules for a specific rule.
176 String installedPackageName = String.format("%s%04d", packageName, 264);
177 String installedAppCertificate = String.format("%s%04d", appCertificate, 1264);
Song Pan95de69d2020-01-10 12:29:35 +0000178 AppInstallMetadata appInstallMetadata =
179 new AppInstallMetadata.Builder()
180 .setPackageName(installedPackageName)
181 .setAppCertificate(installedAppCertificate)
182 .setVersionCode(250)
183 .setInstallerName("abc")
184 .setInstallerCertificate("abc")
185 .setIsPreInstalled(true)
186 .build();
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +0000187 List<Rule> rulesFetched = mIntegrityFileManager.readRules(appInstallMetadata);
188
189 // Verify that we do not load all the rules and we have the necessary rules to evaluate.
Omer Nebil Yaveroglu8d46f342020-01-13 15:28:11 +0000190 assertThat(rulesFetched.size()).isEqualTo(270);
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +0000191 assertThat(rulesFetched)
192 .containsAllOf(
193 getPackageNameIndexedRule(installedPackageName),
194 getAppCertificateIndexedRule(installedAppCertificate));
195 }
196
197 private Rule getPackageNameIndexedRule(String packageName) {
198 return new Rule(
199 new StringAtomicFormula(
Song Pan95de69d2020-01-10 12:29:35 +0000200 AtomicFormula.PACKAGE_NAME, packageName, /* isHashedValue= */ false),
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +0000201 Rule.DENY);
202 }
203
204 private Rule getAppCertificateIndexedRule(String appCertificate) {
205 return new Rule(
206 new StringAtomicFormula(
Song Pan95de69d2020-01-10 12:29:35 +0000207 AtomicFormula.APP_CERTIFICATE, appCertificate, /* isHashedValue= */ false),
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +0000208 Rule.DENY);
209 }
210
211 private Rule getInstallerCertificateRule(String installerCert) {
212 return new Rule(
213 new StringAtomicFormula(
Song Pan95de69d2020-01-10 12:29:35 +0000214 AtomicFormula.INSTALLER_NAME, installerCert, /* isHashedValue= */ false),
Omer Nebil Yaveroglu2948cba2020-01-10 17:51:35 +0000215 Rule.DENY);
Song Panc56a78d2020-01-02 16:06:11 +0000216 }
Song Pan95de69d2020-01-10 12:29:35 +0000217
218 @Test
219 public void testStagingDirectoryCleared() throws Exception {
220 // We must push rules two times to ensure that staging directory is empty because we cleared
221 // it, rather than because original rules directory is empty.
222 mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
223 mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
224
225 assertStagingDirectoryCleared();
226 }
227
228 private void assertStagingDirectoryCleared() {
229 File stagingDir = new File(mTmpDir, "integrity_staging");
230 assertThat(stagingDir.exists()).isTrue();
231 assertThat(stagingDir.isDirectory()).isTrue();
232 assertThat(stagingDir.listFiles()).isEmpty();
233 }
Song Panc56a78d2020-01-02 16:06:11 +0000234}