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