blob: d06fd754593a6bdf00133a233dc1fafc37105752 [file] [log] [blame]
dcashman64560072013-11-06 11:38:25 -08001/*
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
17package android.security.cts;
18
19import android.util.Xml;
20
21import com.google.common.collect.HashMultimap;
22import com.google.common.collect.Multimap;
23import org.xmlpull.v1.XmlPullParser;
24import org.xmlpull.v1.XmlPullParserException;
25
26import java.io.InputStream;
27import java.io.IOException;
28import java.util.ArrayList;
29import java.util.List;
30import java.util.HashMap;
31
32
33/**
34 * A class for generating representations of SELinux avc rules parsed from an xml file.
35 */
36public 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}