1 /* 2 * Copyright (C) 2014 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 android.security.cts; 18 19 import android.util.Xml; 20 21 import com.google.common.collect.HashMultimap; 22 import com.google.common.collect.Multimap; 23 import org.xmlpull.v1.XmlPullParser; 24 import org.xmlpull.v1.XmlPullParserException; 25 26 import java.io.InputStream; 27 import java.io.IOException; 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.HashMap; 31 32 33 /** 34 * A class for generating representations of SELinux avc rules parsed from an xml file. 35 */ 36 public class SELinuxPolicyRule { 37 public final List<String> source_types; 38 public final List<String> target_types; 39 public final Multimap<String, String> obj_classes; 40 public final String name; 41 public final String type; 42 43 private SELinuxPolicyRule(List<String> source_types, List<String> target_types, 44 Multimap<String, String> obj_classes, String name, String type) { 45 this.source_types = source_types; 46 this.target_types = target_types; 47 this.obj_classes = obj_classes; 48 this.name = name; 49 this.type = type; 50 } 51 52 public static SELinuxPolicyRule readRule(XmlPullParser xpp) throws IOException, XmlPullParserException { 53 List<String> source_types = new ArrayList<String>(); 54 List<String> target_types = new ArrayList<String>(); 55 Multimap<String, String> obj_classes = HashMultimap.create(); 56 xpp.require(XmlPullParser.START_TAG, null, "avc_rule"); 57 String ruleName = xpp.getAttributeValue(null, "name"); 58 String ruleType = xpp.getAttributeValue(null, "type"); 59 while (xpp.next() != XmlPullParser.END_TAG) { 60 if (xpp.getEventType() != XmlPullParser.START_TAG) { 61 continue; 62 } 63 String name = xpp.getName(); 64 if (name.equals("type")) { 65 if (xpp.getAttributeValue(null, "type").equals("source")) { 66 source_types.add(readType(xpp)); 67 } else if (xpp.getAttributeValue(null, "type").equals("target")) { 68 target_types.add(readType(xpp)); 69 } else { 70 skip(xpp); 71 } 72 } else if (name.equals("obj_class")) { 73 String obj_name = xpp.getAttributeValue(null, "name"); 74 List<String> perms = readObjClass(xpp); 75 obj_classes.putAll(obj_name, perms); 76 } else { 77 skip(xpp); 78 } 79 } 80 return new SELinuxPolicyRule(source_types, target_types, obj_classes, ruleName, ruleType); 81 } 82 83 public static List<SELinuxPolicyRule> readRulesFile(InputStream in) throws IOException, XmlPullParserException { 84 List<SELinuxPolicyRule> rules = new ArrayList<SELinuxPolicyRule>(); 85 XmlPullParser xpp = Xml.newPullParser(); 86 xpp.setInput(in, null); 87 xpp.nextTag(); 88 xpp.require(XmlPullParser.START_TAG, null, "SELinux_AVC_Rules"); 89 90 /* read rules */ 91 while (xpp.next() != XmlPullParser.END_TAG) { 92 if (xpp.getEventType() != XmlPullParser.START_TAG) { 93 continue; 94 } 95 String name = xpp.getName(); 96 if (name.equals("avc_rule")) { 97 SELinuxPolicyRule r = readRule(xpp); 98 rules.add(r); 99 } else { 100 skip(xpp); 101 } 102 } 103 return rules; 104 } 105 106 private static List<String> readObjClass(XmlPullParser xpp) throws IOException, XmlPullParserException { 107 List<String> perms = new ArrayList<String>(); 108 xpp.require(XmlPullParser.START_TAG, null, "obj_class"); 109 while (xpp.next() != XmlPullParser.END_TAG) { 110 if (xpp.getEventType() != XmlPullParser.START_TAG) { 111 continue; 112 } 113 String name = xpp.getName(); 114 if (name.equals("permission")) { 115 perms.add(readPermission(xpp)); 116 } else { 117 skip(xpp); 118 } 119 } 120 return perms; 121 } 122 123 private static String readType(XmlPullParser xpp) throws IOException, XmlPullParserException { 124 xpp.require(XmlPullParser.START_TAG, null, "type"); 125 String type = readText(xpp); 126 xpp.require(XmlPullParser.END_TAG, null, "type"); 127 return type; 128 } 129 130 private static String readPermission(XmlPullParser xpp) throws IOException, XmlPullParserException { 131 xpp.require(XmlPullParser.START_TAG, null, "permission"); 132 String permission = readText(xpp); 133 xpp.require(XmlPullParser.END_TAG, null, "permission"); 134 return permission; 135 } 136 137 private static String readText(XmlPullParser xpp) throws IOException, XmlPullParserException { 138 String result = ""; 139 if (xpp.next() == XmlPullParser.TEXT) { 140 result = xpp.getText(); 141 xpp.nextTag(); 142 } 143 return result; 144 } 145 146 public static void skip(XmlPullParser xpp) throws XmlPullParserException, IOException { 147 if (xpp.getEventType() != XmlPullParser.START_TAG) { 148 throw new IllegalStateException(); 149 } 150 int depth = 1; 151 while (depth != 0) { 152 switch (xpp.next()) { 153 case XmlPullParser.END_TAG: 154 depth--; 155 break; 156 case XmlPullParser.START_TAG: 157 depth++; 158 break; 159 } 160 } 161 } 162 } 163