Home | History | Annotate | Download | only in cts
      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