1 /*
2  * Copyright (C) 2013 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 com.android.server.firewall;
18 
19 import android.content.ComponentName;
20 import android.content.Intent;
21 import android.content.pm.PackageManagerInternal;
22 import android.os.Process;
23 
24 import org.xmlpull.v1.XmlPullParser;
25 import org.xmlpull.v1.XmlPullParserException;
26 
27 import java.io.IOException;
28 
29 class SenderFilter {
30     private static final String ATTR_TYPE = "type";
31 
32     private static final String VAL_SIGNATURE = "signature";
33     private static final String VAL_SYSTEM = "system";
34     private static final String VAL_SYSTEM_OR_SIGNATURE = "system|signature";
35     private static final String VAL_USER_ID = "userId";
36 
isPrivilegedApp(PackageManagerInternal pmi, int callerUid, int callerPid)37     static boolean isPrivilegedApp(PackageManagerInternal pmi, int callerUid, int callerPid) {
38         if (callerUid == Process.SYSTEM_UID || callerUid == 0 ||
39                 callerPid == Process.myPid() || callerPid == 0) {
40             return true;
41         }
42         return pmi.isUidPrivileged(callerUid);
43     }
44 
45     public static final FilterFactory FACTORY = new FilterFactory("sender") {
46         @Override
47         public Filter newFilter(XmlPullParser parser) throws IOException, XmlPullParserException {
48             String typeString = parser.getAttributeValue(null, ATTR_TYPE);
49             if (typeString == null) {
50                 throw new XmlPullParserException("type attribute must be specified for <sender>",
51                         parser, null);
52             }
53             if (typeString.equals(VAL_SYSTEM)) {
54                 return SYSTEM;
55             } else if (typeString.equals(VAL_SIGNATURE)) {
56                 return SIGNATURE;
57             } else if (typeString.equals(VAL_SYSTEM_OR_SIGNATURE)) {
58                 return SYSTEM_OR_SIGNATURE;
59             } else if (typeString.equals(VAL_USER_ID)) {
60                 return USER_ID;
61             }
62             throw new XmlPullParserException(
63                     "Invalid type attribute for <sender>: " + typeString, parser, null);
64         }
65     };
66 
67     private static final Filter SIGNATURE = new Filter() {
68         @Override
69         public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
70                 int callerUid, int callerPid, String resolvedType, int receivingUid) {
71             return ifw.signaturesMatch(callerUid, receivingUid);
72         }
73     };
74 
75     private static final Filter SYSTEM = new Filter() {
76         @Override
77         public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
78                 int callerUid, int callerPid, String resolvedType, int receivingUid) {
79             return isPrivilegedApp(ifw.getPackageManager(), callerUid, callerPid);
80         }
81     };
82 
83     private static final Filter SYSTEM_OR_SIGNATURE = new Filter() {
84         @Override
85         public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
86                 int callerUid, int callerPid, String resolvedType, int receivingUid) {
87             return isPrivilegedApp(ifw.getPackageManager(), callerUid, callerPid)
88                     || ifw.signaturesMatch(callerUid, receivingUid);
89         }
90     };
91 
92     private static final Filter USER_ID = new Filter() {
93         @Override
94         public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
95                 int callerUid, int callerPid, String resolvedType, int receivingUid) {
96             // This checks whether the caller is either the system process, or has the same user id
97             // I.e. the same app, or an app that uses the same shared user id.
98             // This is the same set of applications that would be able to access the component if
99             // it wasn't exported.
100             return ifw.checkComponentPermission(null, callerPid, callerUid, receivingUid, false);
101         }
102     };
103 }
104