blob: d06fd754593a6bdf00133a233dc1fafc37105752 [file] [log] [blame]
/*
* Copyright (C) 2014 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.security.cts;
import android.util.Xml;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
/**
* A class for generating representations of SELinux avc rules parsed from an xml file.
*/
public class SELinuxPolicyRule {
public final List<String> source_types;
public final List<String> target_types;
public final Multimap<String, String> obj_classes;
public final String name;
public final String type;
private SELinuxPolicyRule(List<String> source_types, List<String> target_types,
Multimap<String, String> obj_classes, String name, String type) {
this.source_types = source_types;
this.target_types = target_types;
this.obj_classes = obj_classes;
this.name = name;
this.type = type;
}
public static SELinuxPolicyRule readRule(XmlPullParser xpp) throws IOException, XmlPullParserException {
List<String> source_types = new ArrayList<String>();
List<String> target_types = new ArrayList<String>();
Multimap<String, String> obj_classes = HashMultimap.create();
xpp.require(XmlPullParser.START_TAG, null, "avc_rule");
String ruleName = xpp.getAttributeValue(null, "name");
String ruleType = xpp.getAttributeValue(null, "type");
while (xpp.next() != XmlPullParser.END_TAG) {
if (xpp.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = xpp.getName();
if (name.equals("type")) {
if (xpp.getAttributeValue(null, "type").equals("source")) {
source_types.add(readType(xpp));
} else if (xpp.getAttributeValue(null, "type").equals("target")) {
target_types.add(readType(xpp));
} else {
skip(xpp);
}
} else if (name.equals("obj_class")) {
String obj_name = xpp.getAttributeValue(null, "name");
List<String> perms = readObjClass(xpp);
obj_classes.putAll(obj_name, perms);
} else {
skip(xpp);
}
}
return new SELinuxPolicyRule(source_types, target_types, obj_classes, ruleName, ruleType);
}
public static List<SELinuxPolicyRule> readRulesFile(InputStream in) throws IOException, XmlPullParserException {
List<SELinuxPolicyRule> rules = new ArrayList<SELinuxPolicyRule>();
XmlPullParser xpp = Xml.newPullParser();
xpp.setInput(in, null);
xpp.nextTag();
xpp.require(XmlPullParser.START_TAG, null, "SELinux_AVC_Rules");
/* read rules */
while (xpp.next() != XmlPullParser.END_TAG) {
if (xpp.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = xpp.getName();
if (name.equals("avc_rule")) {
SELinuxPolicyRule r = readRule(xpp);
rules.add(r);
} else {
skip(xpp);
}
}
return rules;
}
private static List<String> readObjClass(XmlPullParser xpp) throws IOException, XmlPullParserException {
List<String> perms = new ArrayList<String>();
xpp.require(XmlPullParser.START_TAG, null, "obj_class");
while (xpp.next() != XmlPullParser.END_TAG) {
if (xpp.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = xpp.getName();
if (name.equals("permission")) {
perms.add(readPermission(xpp));
} else {
skip(xpp);
}
}
return perms;
}
private static String readType(XmlPullParser xpp) throws IOException, XmlPullParserException {
xpp.require(XmlPullParser.START_TAG, null, "type");
String type = readText(xpp);
xpp.require(XmlPullParser.END_TAG, null, "type");
return type;
}
private static String readPermission(XmlPullParser xpp) throws IOException, XmlPullParserException {
xpp.require(XmlPullParser.START_TAG, null, "permission");
String permission = readText(xpp);
xpp.require(XmlPullParser.END_TAG, null, "permission");
return permission;
}
private static String readText(XmlPullParser xpp) throws IOException, XmlPullParserException {
String result = "";
if (xpp.next() == XmlPullParser.TEXT) {
result = xpp.getText();
xpp.nextTag();
}
return result;
}
public static void skip(XmlPullParser xpp) throws XmlPullParserException, IOException {
if (xpp.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (xpp.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
}