summaryrefslogtreecommitdiffstats
path: root/core/tests/coretests/src/android/content/pm/SELinuxMMACTests.java
blob: b0a7979c6c4a57f8e1bdf69a54e2c447430ae522 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.content.pm;

import android.content.pm.PackageManagerTests;
import android.content.pm.SELinuxMMAC;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.net.Uri;
import android.os.FileUtils;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.DisplayMetrics;
import android.util.Log;

import com.android.frameworks.coretests.R;

import java.io.File;
import java.io.FileReader;
import java.io.InputStream;

public class SELinuxMMACTests extends AndroidTestCase {

    private static final String TAG = "SELinuxMMACTests";

    private static File MAC_INSTALL_TMP;
    private static File APK_INSTALL_TMP;
    private static final String MAC_INSTALL_TMP_NAME = "mac_install_policy";
    private static final String APK_INSTALL_TMP_NAME = "install.apk";

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        // Need a tmp file to hold the various mmac install files.
        File filesDir = mContext.getFilesDir();
        MAC_INSTALL_TMP = new File(filesDir, MAC_INSTALL_TMP_NAME);
        assertNotNull(MAC_INSTALL_TMP);

        // Need a tmp file to hold the apk
        APK_INSTALL_TMP = new File(filesDir, APK_INSTALL_TMP_NAME);
        assertNotNull(APK_INSTALL_TMP);
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();

        // Just in case still around
        MAC_INSTALL_TMP.delete();
        APK_INSTALL_TMP.delete();
    }

    void failStr(String errMsg) {
        Log.w(TAG, "errMsg="+errMsg);
        fail(errMsg);
    }

    void failStr(Exception e) {
        failStr(e.getMessage());
    }

    private PackageParser.Package parsePackage(Uri packageURI) {
        final String archiveFilePath = packageURI.getPath();
        PackageParser packageParser = new PackageParser(archiveFilePath);
        File sourceFile = new File(archiveFilePath);
        DisplayMetrics metrics = new DisplayMetrics();
        metrics.setToDefaults();
        PackageParser.Package pkg = packageParser.parsePackage(sourceFile,
                                                               archiveFilePath,
                                                               metrics, 0);
        assertNotNull(pkg);
        assertTrue(packageParser.collectCertificates(pkg,0));
        packageParser = null;
        return pkg;
    }

    Uri getResourceURI(int fileResId, File outFile) {
        Resources res = mContext.getResources();
        InputStream is = null;
        try {
            is = res.openRawResource(fileResId);
        } catch (NotFoundException e) {
            failStr("Failed to load resource with id: " + fileResId);
        }
        assertNotNull(is);
        FileUtils.setPermissions(outFile.getPath(),
                                 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO,
                                 -1, -1);
        assertTrue(FileUtils.copyToFile(is, outFile));
        FileUtils.setPermissions(outFile.getPath(),
                                 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO,
                                 -1, -1);
        return Uri.fromFile(outFile);
    }

    /**
     * Takes the policy xml file as a resource, the apk as a resource,
     * the expected seinfo string, and the expected install value.
     * We mock a package install here by calling parsePackage.
     */
    void checkInstallMMAC(int policyRes, int apkRes,
                          String expectedSeinfo,
                          boolean expectedPassed) {
        // grab policy file
        Uri policyURI = getResourceURI(policyRes, MAC_INSTALL_TMP);
        assertNotNull(policyURI);
        // parse the policy file
        boolean ret = SELinuxMMAC.readInstallPolicy(new File(policyURI.getPath()));
        assertTrue(ret);
        // grab the apk
        Uri apkURI = getResourceURI(apkRes, APK_INSTALL_TMP);
        assertNotNull(apkURI);
        // "install" the apk
        PackageParser.Package pkg = parsePackage(apkURI);
        assertNotNull(pkg);
        assertNotNull(pkg.packageName);
        // check for correct passed policy value
        boolean passed = SELinuxMMAC.passInstallPolicyChecks(pkg);
        assertEquals(expectedPassed, passed);
        // check for correct seinfo label
        String seinfo = pkg.applicationInfo.seinfo;
        if (seinfo == null)
            seinfo = "null";
        assertEquals(expectedSeinfo, seinfo);

        // delete policy and apk
        MAC_INSTALL_TMP.delete();
        APK_INSTALL_TMP.delete();
    }

    /*
     * Requested policy file doesn't exist.
     */
    @LargeTest
    public void testINSTALL_POLICY_BADPATH() {
        boolean ret = SELinuxMMAC.readInstallPolicy(new File("/d/o/e/s/n/t/e/x/i/s/t"));
        assertFalse(ret);
    }

    /*
     * Requested policy file is null object.
     */
    @LargeTest
    public void testINSTALL_POLICY_NULL() {
        boolean ret = SELinuxMMAC.readInstallPolicy(null);
        assertFalse(ret);
    }

    /*
     * No need to test a valid install policy file. All the tests
     * below test it implicitly.
     */

    /*
     * Signature stanza hits. apk is installed from allow-all.
     */
    @LargeTest
    public void testSIGNATURE_ALLOWALL_INSTALLED() {
        checkInstallMMAC(R.raw.mmac_sig_all, R.raw.signed_platform,
                         "platform", true);
    }

    /*
     * Signature stanza hits. apk is installed from whitelist.
     */
    @LargeTest
    public void testSIGNATURE_WHITELIST_INSTALLED() {
        checkInstallMMAC(R.raw.mmac_sig_white, R.raw.signed_platform,
                         "platform", true);
    }

    /*
     * Signature stanza hits. apk is installed from blacklist.
     */
    @LargeTest
    public void testSIGNATURE_BLACKLIST_INSTALLED() {
        checkInstallMMAC(R.raw.mmac_sig_black, R.raw.signed_platform,
                         "platform", true);
    }

    /*
     * Signature stanza hits. apk is installed. null seinfo tag.
     */
    @LargeTest
    public void testSIGNATURE_INSTALLED_NULL_SEINFO() {
        checkInstallMMAC(R.raw.mmac_sig_null, R.raw.signed_platform,
                         "null", true);
    }

    /*
     * Signature stanza hits. apk is denied.
     * Package stanza allows.
     */
    @LargeTest
    public void testSIGNATURE_DENIED_PACKAGE_ALLOWS() {
        checkInstallMMAC(R.raw.mmac_sig_deny_pkg_allow, R.raw.signed_platform,
                         "package", true);
    }

    /*
     * Signature stanza hits. apk is denied.
     * Package stanza then denys.
     */
    @LargeTest
    public void testSIGNATURE_DENIED_PACKAGE_DENY() {
        checkInstallMMAC(R.raw.mmac_sig_deny_pkg_deny, R.raw.signed_platform,
                         "null", false);
    }

    /*
     * Signature stanza hits. apk is denied.
     * Default stanza allows.
     */
    @LargeTest
    public void testSIGNATURE_DENIED_DEFAULT_ALLOWS() {
        checkInstallMMAC(R.raw.mmac_sig_deny_default_allow, R.raw.signed_platform,
                         "default", true);
    }

    /*
     * Signature stanza hits yet denys. Default stanza hits and denys.
     */
    @LargeTest
    public void testSIGNATURE_DENY_DEFAULT_DENY() {
        checkInstallMMAC(R.raw.mmac_sig_deny_default_deny, R.raw.signed_platform,
                         "null", false);
    }

    /*
     * Signature stanza hits. apk is denied.
     * No other policy present.
     */
    @LargeTest
    public void testSIGNATURE_DENIED_NOOTHER_POLICY() {
        checkInstallMMAC(R.raw.mmac_sig_deny_noother, R.raw.signed_platform,
                         "null", false);
    }

    /*
     * Package stanza hits. apk is installed from allow-all.
     */
    @LargeTest
    public void testPACKAGE_ALLOWALL_INSTALLED() {
        checkInstallMMAC(R.raw.mmac_pkg_all, R.raw.signed_platform,
                         "package", true);
    }

    /*
     * Package stanza hits. apk is installed from whitelist.
     */
    @LargeTest
    public void testPACKAGE_WHITELIST_INSTALLED() {
        checkInstallMMAC(R.raw.mmac_pkg_white, R.raw.signed_platform,
                         "package", true);
    }

    /*
     * Package stanza hits. apk is installed from blacklist.
     */
    @LargeTest
    public void testPACKAGE_BLACKLIST_INSTALLED() {
        checkInstallMMAC(R.raw.mmac_pkg_black, R.raw.signed_platform,
                         "package", true);
    }

    /*
     * Package stanza hits. apk is installed. seinfo is null.
     */
    @LargeTest
    public void testPACKAGE_INSTALLED_NULL_SEINFO() {
        checkInstallMMAC(R.raw.mmac_pkg_null_seinfo, R.raw.signed_platform,
                         "null", true);
    }

    /*
     * Package stanza hits. apk is denied on whitelist.
     */
    @LargeTest
    public void testPACKAGE_WHITELIST_DENIED() {
        checkInstallMMAC(R.raw.mmac_pkg_deny_white, R.raw.signed_platform,
                         "null", false);
    }

    /*
     * Package stanza hits. apk is denied on blacklist.
     */
    @LargeTest
    public void testPACKAGE_BLACKLIST_DENIED() {
        checkInstallMMAC(R.raw.mmac_pkg_deny_black, R.raw.signed_platform,
                         "null", false);
    }

    /*
     * Default stanza hits. apk is installed from allowall.
     */
     @LargeTest
     public void testDEFAULT_ALLOWALL_INSTALLED() {
         checkInstallMMAC(R.raw.mmac_default_all, R.raw.signed_platform,
                          "default", true);
    }

    /*
     * Default stanza hits. apk is installed from whitelist.
     */
    @LargeTest
    public void testDEFAULT_WHITELIST_INSTALLED() {
        checkInstallMMAC(R.raw.mmac_default_white, R.raw.signed_platform,
                         "default", true);
    }

    /*
     * Default stanza hits. apk is installed from blacklist.
     */
    @LargeTest
    public void testDEFAULT_BLACKLIST_INSTALLED() {
        checkInstallMMAC(R.raw.mmac_default_black, R.raw.signed_platform,
                         "default", true);
    }

    /*
     * Default stanza hits. apk installed. null seinfo.
     */
    @LargeTest
    public void testDEFAULT_INSTALLED_NULL_SEINFO() {
        checkInstallMMAC(R.raw.mmac_default_null_seinfo, R.raw.signed_platform,
                         "null", true);
        }

    /*
     * Default stanza hits. apk is denied on whitelist.
     */
    @LargeTest
    public void testDEFAULT_WHITELIST_DENIED() {
        checkInstallMMAC(R.raw.mmac_default_white_deny, R.raw.signed_platform,
                         "null", false);
        }

    /*
     * Default stanza hits. apk is denied on blacklist.
     */
    @LargeTest
    public void testDEFAULT_BLACKLIST_DENIED() {
        checkInstallMMAC(R.raw.mmac_default_black_deny, R.raw.signed_platform,
                         "null", false);
    }

    /*
     * No matching entry in policy.
     */
    @LargeTest
    public void testNO_MATCHING_POLICY() {
        checkInstallMMAC(R.raw.mmac_no_match, R.raw.signed_platform,
                         "null", false);
    }

    /*
     * Signature catches yet there is a package stanza inside that allows
     * based on allow-all.
     */
    @LargeTest
    public void testPACKAGE_INSIDE_SIG_ALLOW_ALL() {
        checkInstallMMAC(R.raw.mmac_inside_pkg_allow_all, R.raw.signed_platform,
                         "insidepackage", true);
    }

    /*
     * Signature catches yet there is a package stanza inside that allows
     * based on whitelist.
     */
    @LargeTest
    public void testPACKAGE_INSIDE_SIG_ALLOW_WHITE() {
        checkInstallMMAC(R.raw.mmac_inside_pkg_allow_white, R.raw.signed_platform,
                         "insidepackage", true);
    }

    /*
     * Signature catches yet there is a package stanza inside that allows
     * based on blacklist.
     */
    @LargeTest
    public void testPACKAGE_INSIDE_SIG_ALLOW_BLACK() {
        checkInstallMMAC(R.raw.mmac_inside_pkg_allow_black, R.raw.signed_platform,
                         "insidepackage", true);
    }

    /*
     * Signature catches yet there is a package stanza inside that denies
     * based on blacklist. Stand alone package stanza then allows.
     */
    @LargeTest
    public void testPACKAGE_INSIDE_SIG_DENY_PKG_OUT_ALLOWS() {
        checkInstallMMAC(R.raw.mmac_inside_pkg_deny_pkg, R.raw.signed_platform,
                         "package", true);
    }

    /*
     * Signature catches yet there is a package stanza inside that denies
     * based on whitelist. default stanza catches and allows.
     */
    @LargeTest
    public void testPACKAGE_INSIDE_SIG_DENY_DEFAULT_ALLOWS() {
        checkInstallMMAC(R.raw.mmac_inside_pkg_deny_default, R.raw.signed_platform,
                         "default", true);
    }

    /*
     * Signature catches yet there is a package stanza inside that denies.
     * No other policy catches. app is denied.
     */
    @LargeTest
    public void testPACKAGE_INSIDE_SIG_DENY_NOOTHER() {
        checkInstallMMAC(R.raw.mmac_inside_pkg_deny_noother, R.raw.signed_platform,
                         "null", false);
    }

    /*
     * Signature catches yet there is a package stanza inside that allows.
     * However, the seingo tag is null.
     */
    @LargeTest
    public void testPACKAGE_INSIDE_SIG_ALLOWS_NULL_SEINFO() {
        checkInstallMMAC(R.raw.mmac_inside_pkg_allow_null_seinfo, R.raw.signed_platform,
                         "null", true);
    }

    /*
     * Signature stanza has inner package stanza. Outer sig stanza
     * has no rules. Check app signed with same key, diff pkg name, doesn't
     * catch on outer signer stanza. Catches on default though.
     */
    @LargeTest
    public void testPACKAGE_SAME_CERT_DIFF_NAME_SKIPS_OUTER() {
        checkInstallMMAC(R.raw.mmac_diff_name_skip_outer, R.raw.signed_platform_2,
                         "default", true);
    }

    /*
     * Signature stanza has inner package stanza. Outer sig stanza
     * has no rules. Check app catches on inner.
     */
    @LargeTest
    public void testPACKAGE_INNER_HITS_NO_OUTER_RULES() {
        checkInstallMMAC(R.raw.mmac_outer_no_rule_catch_inner, R.raw.signed_platform,
                         "insidepackage", true);
    }

    /*
     * Signature stanza has inner package stanza with no seinfo tag.
     * Outer sig stanza has no rules but seinfo tag. Check app labeled null.
     */
    @LargeTest
    public void testPACKAGE_INSIDE_SIG_ALLOWS_NULL_SEINFO_OUTER_SEINFO_MISSED() {
        checkInstallMMAC(R.raw.mmac_inner_seinfo_null_outer_seinfo, R.raw.signed_platform,
                         "null", true);
    }

    /*
     * Signature stanza has inner package stanza. Outer sig stanza
     * has blacklist. Check app signed with same key, diff pkg name,
     * denied on outer signer stanza. Catches on default though.
     */
    @LargeTest
    public void testPACKAGE_SAME_CERT_DIFF_NAME_DENIED_OUTER() {
        checkInstallMMAC(R.raw.mmac_diff_name_deny_outer, R.raw.signed_platform_2,
                         "default", true);
    }

    /*
     * Signature stanza has inner package stanza. Check that app
     * with same package name, diff key, catches on another cert.
     */
    @LargeTest
    public void testPACKAGE_DIFF_CERT_SAME_NAME() {
        checkInstallMMAC(R.raw.mmac_same_name_diff_cert, R.raw.signed_media,
                         "media", true);
    }

    /*
     * Default stanza with inner package that hits. Outer not empty.
     */
    @LargeTest
    public void testPACKAGE_INNER_DEFAULT() {
        checkInstallMMAC(R.raw.mmac_default_inner_pkg, R.raw.signed_media,
                         "insidedefault", true);
    }

    /*
     * Default stanza with inner package that hits. Outer empty.
     */
    @LargeTest
    public void testPACKAGE_INNER_DEFAULT_OUTER_EMPTY() {
        checkInstallMMAC(R.raw.mmac_default_inner_pkg_out_empty, R.raw.signed_media,
                         "insidedefault", true);
    }

    /*
     * Default stanza with inner package that denies.
     */
    @LargeTest
    public void testPACKAGE_INNER_DEFAULT_DENY() {
        checkInstallMMAC(R.raw.mmac_default_inner_pkg_deny, R.raw.signed_media,
                         "null", false);
    }
}