diff options
4 files changed, 335 insertions, 291 deletions
diff --git a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java index 23d0b40f08f6..11a397948b14 100644 --- a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java +++ b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java @@ -40,16 +40,16 @@ public final class RuleXmlParser implements RuleParser { public static final String TAG = "RuleXmlParser"; - // TODO: Use XML attributes + private static final String NAMESPACE = ""; private static final String RULE_LIST_TAG = "RL"; private static final String RULE_TAG = "R"; private static final String OPEN_FORMULA_TAG = "OF"; private static final String ATOMIC_FORMULA_TAG = "AF"; - private static final String EFFECT_TAG = "E"; - private static final String KEY_TAG = "K"; - private static final String OPERATOR_TAG = "O"; - private static final String VALUE_TAG = "V"; - private static final String CONNECTOR_TAG = "C"; + private static final String EFFECT_ATTRIBUTE = "E"; + private static final String KEY_ATTRIBUTE = "K"; + private static final String OPERATOR_ATTRIBUTE = "O"; + private static final String VALUE_ATTRIBUTE = "V"; + private static final String CONNECTOR_ATTRIBUTE = "C"; @Override public List<Rule> parse(String ruleText) throws RuleParseException { @@ -106,7 +106,7 @@ public final class RuleXmlParser implements RuleParser { private static Rule parseRule(XmlPullParser parser) throws IOException, XmlPullParserException { Formula formula = null; - @Rule.Effect int effect = 0; + @Rule.Effect int effect = Integer.parseInt(extractAttributeValue(parser, EFFECT_ATTRIBUTE)); int eventType; while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) { @@ -124,9 +124,6 @@ public final class RuleXmlParser implements RuleParser { case ATOMIC_FORMULA_TAG: formula = parseAtomicFormula(parser); break; - case EFFECT_TAG: - effect = Integer.parseInt(extractValue(parser)); - break; default: throw new RuntimeException( String.format("Found unexpected tag: %s", nodeName)); @@ -142,7 +139,8 @@ public final class RuleXmlParser implements RuleParser { private static Formula parseOpenFormula(XmlPullParser parser) throws IOException, XmlPullParserException { - @OpenFormula.Connector int connector = 0; + @OpenFormula.Connector int connector = Integer.parseInt( + extractAttributeValue(parser, CONNECTOR_ATTRIBUTE)); List<Formula> formulas = new ArrayList<>(); int eventType; @@ -155,9 +153,6 @@ public final class RuleXmlParser implements RuleParser { if (eventType == XmlPullParser.START_TAG) { switch (nodeName) { - case CONNECTOR_TAG: - connector = Integer.parseInt(extractValue(parser)); - break; case ATOMIC_FORMULA_TAG: formulas.add(parseAtomicFormula(parser)); break; @@ -179,37 +174,16 @@ public final class RuleXmlParser implements RuleParser { private static Formula parseAtomicFormula(XmlPullParser parser) throws IOException, XmlPullParserException { - @AtomicFormula.Key int key = 0; - @AtomicFormula.Operator int operator = 0; - String value = null; + @AtomicFormula.Key int key = Integer.parseInt(extractAttributeValue(parser, KEY_ATTRIBUTE)); + @AtomicFormula.Operator int operator = Integer.parseInt( + extractAttributeValue(parser, OPERATOR_ATTRIBUTE)); + String value = extractAttributeValue(parser, VALUE_ATTRIBUTE); int eventType; while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) { - String nodeName = parser.getName(); - if (eventType == XmlPullParser.END_TAG && parser.getName().equals(ATOMIC_FORMULA_TAG)) { break; } - - if (eventType == XmlPullParser.START_TAG) { - switch (nodeName) { - case KEY_TAG: - key = Integer.parseInt(extractValue(parser)); - break; - case OPERATOR_TAG: - operator = Integer.parseInt(extractValue(parser)); - break; - case VALUE_TAG: - value = extractValue(parser); - break; - default: - throw new RuntimeException( - String.format("Found unexpected tag: %s", nodeName)); - } - } else { - throw new RuntimeException( - String.format("Found unexpected event type: %d", eventType)); - } } return constructAtomicFormulaBasedOnKey(key, operator, value); } @@ -231,17 +205,11 @@ public final class RuleXmlParser implements RuleParser { } } - private static String extractValue(XmlPullParser parser) - throws IOException, XmlPullParserException { - String value; - int eventType = parser.next(); - if (eventType == XmlPullParser.TEXT) { - value = parser.getText(); - eventType = parser.next(); - if (eventType == XmlPullParser.END_TAG) { - return value; - } + private static String extractAttributeValue(XmlPullParser parser, String attribute) { + String attributeValue = parser.getAttributeValue(NAMESPACE, attribute); + if (attributeValue == null) { + throw new RuntimeException(String.format("Attribute not found: %s", attribute)); } - throw new RuntimeException(String.format("Found unexpected event type: %d", eventType)); + return attributeValue; } } diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java index b0805fc488cb..1f22afb0e9bf 100644 --- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java +++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java @@ -43,11 +43,11 @@ public class RuleXmlSerializer implements RuleSerializer { private static final String RULE_TAG = "R"; private static final String OPEN_FORMULA_TAG = "OF"; private static final String ATOMIC_FORMULA_TAG = "AF"; - private static final String EFFECT_TAG = "E"; - private static final String KEY_TAG = "K"; - private static final String OPERATOR_TAG = "O"; - private static final String VALUE_TAG = "V"; - private static final String CONNECTOR_TAG = "C"; + private static final String EFFECT_ATTRIBUTE = "E"; + private static final String KEY_ATTRIBUTE = "K"; + private static final String OPERATOR_ATTRIBUTE = "O"; + private static final String VALUE_ATTRIBUTE = "V"; + private static final String CONNECTOR_ATTRIBUTE = "C"; @Override public void serialize(List<Rule> rules, OutputStream outputStream) @@ -88,8 +88,8 @@ public class RuleXmlSerializer implements RuleSerializer { return; } xmlSerializer.startTag(NAMESPACE, RULE_TAG); + serializeAttributeValue(EFFECT_ATTRIBUTE, String.valueOf(rule.getEffect()), xmlSerializer); serializeFormula(rule.getFormula(), xmlSerializer); - serializeValue(EFFECT_TAG, String.valueOf(rule.getEffect()), xmlSerializer); xmlSerializer.endTag(NAMESPACE, RULE_TAG); } @@ -110,7 +110,8 @@ public class RuleXmlSerializer implements RuleSerializer { return; } xmlSerializer.startTag(NAMESPACE, OPEN_FORMULA_TAG); - serializeValue(CONNECTOR_TAG, String.valueOf(openFormula.getConnector()), xmlSerializer); + serializeAttributeValue(CONNECTOR_ATTRIBUTE, String.valueOf(openFormula.getConnector()), + xmlSerializer); for (Formula formula : openFormula.getFormulas()) { serializeFormula(formula, xmlSerializer); } @@ -123,19 +124,20 @@ public class RuleXmlSerializer implements RuleSerializer { return; } xmlSerializer.startTag(NAMESPACE, ATOMIC_FORMULA_TAG); - serializeValue(KEY_TAG, String.valueOf(atomicFormula.getKey()), xmlSerializer); + serializeAttributeValue(KEY_ATTRIBUTE, String.valueOf(atomicFormula.getKey()), + xmlSerializer); if (atomicFormula instanceof AtomicFormula.StringAtomicFormula) { - serializeValue(VALUE_TAG, + serializeAttributeValue(VALUE_ATTRIBUTE, ((AtomicFormula.StringAtomicFormula) atomicFormula).getValue(), xmlSerializer); } else if (atomicFormula instanceof AtomicFormula.IntAtomicFormula) { - serializeValue(OPERATOR_TAG, + serializeAttributeValue(OPERATOR_ATTRIBUTE, String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getOperator()), xmlSerializer); - serializeValue(VALUE_TAG, + serializeAttributeValue(VALUE_ATTRIBUTE, String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getValue()), xmlSerializer); } else if (atomicFormula instanceof AtomicFormula.BooleanAtomicFormula) { - serializeValue(VALUE_TAG, + serializeAttributeValue(VALUE_ATTRIBUTE, String.valueOf(((AtomicFormula.BooleanAtomicFormula) atomicFormula).getValue()), xmlSerializer); } else { @@ -145,13 +147,12 @@ public class RuleXmlSerializer implements RuleSerializer { xmlSerializer.endTag(NAMESPACE, ATOMIC_FORMULA_TAG); } - private void serializeValue(String tag, String value, XmlSerializer xmlSerializer) + private void serializeAttributeValue(String attribute, String value, + XmlSerializer xmlSerializer) throws IOException { if (value == null) { return; } - xmlSerializer.startTag(NAMESPACE, tag); - xmlSerializer.text(value); - xmlSerializer.endTag(NAMESPACE, tag); + xmlSerializer.attribute(NAMESPACE, attribute, value); } } diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java index 975689db5264..be6a31fa949e 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java @@ -32,24 +32,28 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; @RunWith(JUnit4.class) public class RuleXmlParserTest { @Test public void testXmlStream_validOpenFormula() throws Exception { + Map<String, String> atomicFormulaAttrs = new HashMap<>(); + atomicFormulaAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + atomicFormulaAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + atomicFormulaAttrs.put("V", "com.app.test"); String ruleXmlOpenFormula = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.NOT + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -65,17 +69,19 @@ public class RuleXmlParserTest { @Test public void testXmlString_validOpenFormula_notConnector() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + packageNameAttrs.put("V", "com.app.test"); String ruleXmlOpenFormula = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.NOT + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -90,22 +96,24 @@ public class RuleXmlParserTest { @Test public void testXmlString_validOpenFormula_andConnector() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + packageNameAttrs.put("V", "com.app.test"); + Map<String, String> appCertificateAttrs = new HashMap<>(); + appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE)); + appCertificateAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + appCertificateAttrs.put("V", "test_cert"); String ruleXmlOpenFormula = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.AND + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" - + "<AF>" - + "<K>" + AtomicFormula.APP_CERTIFICATE + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>test_cert</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.AND)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + + generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -121,22 +129,24 @@ public class RuleXmlParserTest { @Test public void testXmlString_validOpenFormula_orConnector() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + packageNameAttrs.put("V", "com.app.test"); + Map<String, String> appCertificateAttrs = new HashMap<>(); + appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE)); + appCertificateAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + appCertificateAttrs.put("V", "test_cert"); String ruleXmlOpenFormula = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.OR + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" - + "<AF>" - + "<K>" + AtomicFormula.APP_CERTIFICATE + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>test_cert</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.OR)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + + generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -152,17 +162,19 @@ public class RuleXmlParserTest { @Test public void testXmlString_validOpenFormula_differentTagOrder() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("V", "com.app.test"); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); String ruleXmlOpenFormula = "<RL>" - + "<R>" - + "<OF>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" - + "<C>" + OpenFormula.NOT + "</C>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -177,22 +189,24 @@ public class RuleXmlParserTest { @Test public void testXmlString_invalidOpenFormula_invalidNumberOfFormulas() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + packageNameAttrs.put("V", "com.app.test"); + Map<String, String> versionCodeAttrs = new HashMap<>(); + versionCodeAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE)); + versionCodeAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + versionCodeAttrs.put("V", "1"); String ruleXmlOpenFormula = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.NOT + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" - + "<AF>" - + "<K>" + AtomicFormula.VERSION_CODE + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>1</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + + generateTagWithAttribute(/* tag= */ "AF", versionCodeAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -205,17 +219,19 @@ public class RuleXmlParserTest { @Test public void testXmlString_invalidOpenFormula_invalidOperator() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("O", "INVALID_OPERATOR"); + packageNameAttrs.put("V", "com.app.test"); String ruleXmlOpenFormula = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.NOT + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>INVALID_OPERATOR</O>" - + "<V>com.app.test</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -228,17 +244,19 @@ public class RuleXmlParserTest { @Test public void testXmlString_invalidOpenFormula_invalidEffect() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + packageNameAttrs.put("V", "com.app.test"); String ruleXmlOpenFormula = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.NOT + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", "INVALID_EFFECT"), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</OF>" - + "<E>INVALID_EFFECT</E>" + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -251,37 +269,41 @@ public class RuleXmlParserTest { @Test public void testXmlString_invalidOpenFormula_invalidTags() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + packageNameAttrs.put("V", "com.app.test"); String ruleXmlOpenFormula = "<RL>" - + "<R>" - + "<OF>" - + "<InvalidConnector>" + OpenFormula.NOT + "</InvalidConnector>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "InvalidAtomicFormula", + packageNameAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); assertExpectException( RuleParseException.class, - /* expectedExceptionMessageRegex */ "Found unexpected tag: InvalidConnector", + /* expectedExceptionMessageRegex */ "Found unexpected tag: InvalidAtomicFormula", () -> xmlParser.parse(ruleXmlOpenFormula)); } @Test public void testXmlString_validAtomicFormula_stringValue() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + packageNameAttrs.put("V", "com.app.test"); String ruleXmlAtomicFormula = "<RL>" - + "<R>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" - + "<E>" + Rule.DENY + "</E>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -296,14 +318,15 @@ public class RuleXmlParserTest { @Test public void testXmlString_validAtomicFormula_integerValue() throws Exception { + Map<String, String> versionCodeAttrs = new HashMap<>(); + versionCodeAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE)); + versionCodeAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + versionCodeAttrs.put("V", "1"); String ruleXmlAtomicFormula = "<RL>" - + "<R>" - + "<AF>" - + "<K>" + AtomicFormula.VERSION_CODE + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>1</V>" - + "</AF>" - + "<E>" + Rule.DENY + "</E>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", versionCodeAttrs, /* closed= */ true) + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -318,14 +341,15 @@ public class RuleXmlParserTest { @Test public void testXmlString_validAtomicFormula_booleanValue() throws Exception { + Map<String, String> preInstalledAttrs = new HashMap<>(); + preInstalledAttrs.put("K", String.valueOf(AtomicFormula.PRE_INSTALLED)); + preInstalledAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + preInstalledAttrs.put("V", "true"); String ruleXmlAtomicFormula = "<RL>" - + "<R>" - + "<AF>" - + "<K>" + AtomicFormula.PRE_INSTALLED + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>true</V>" - + "</AF>" - + "<E>" + Rule.DENY + "</E>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", preInstalledAttrs, /* closed= */ true) + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -339,15 +363,16 @@ public class RuleXmlParserTest { } @Test - public void testXmlString_validAtomicFormula_differentTagOrder() throws Exception { + public void testXmlString_validAtomicFormula_differentAttributeOrder() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("V", "com.app.test"); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); String ruleXmlAtomicFormula = "<RL>" - + "<R>" - + "<AF>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "</AF>" - + "<E>" + Rule.DENY + "</E>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -361,35 +386,37 @@ public class RuleXmlParserTest { } @Test - public void testXmlString_invalidAtomicFormula_invalidTags() throws Exception { + public void testXmlString_invalidAtomicFormula_invalidAttribute() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("BadKey", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + packageNameAttrs.put("V", "com.app.test"); String ruleXmlAtomicFormula = "<RL>" - + "<R>" - + "<AF>" - + "<BadKey>" + AtomicFormula.PACKAGE_NAME + "</BadKey>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" - + "<E>" + Rule.DENY + "</E>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); assertExpectException( RuleParseException.class, - /* expectedExceptionMessageRegex */ "Found unexpected tag: BadKey", + /* expectedExceptionMessageRegex */ "Attribute not found: K", () -> xmlParser.parse(ruleXmlAtomicFormula)); } @Test public void testXmlString_invalidAtomicFormula() throws Exception { + Map<String, String> packageNameAttrs = new HashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE)); + packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + packageNameAttrs.put("V", "com.app.test"); String ruleXmlAtomicFormula = "<RL>" - + "<R>" - + "<AF>" - + "<K>" + AtomicFormula.VERSION_CODE + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" - + "<E>" + Rule.DENY + "</E>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</R>" + "</RL>"; RuleParser xmlParser = new RuleXmlParser(); @@ -402,16 +429,18 @@ public class RuleXmlParserTest { @Test public void testXmlString_withNoRuleList() { - String ruleXmlWithNoRuleList = "<R>" - + "<OF>" - + "<C>" + OpenFormula.NOT + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" + Map<String, String> atomicFormulaAttrs = new HashMap<>(); + atomicFormulaAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + atomicFormulaAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + atomicFormulaAttrs.put("V", "com.app.test"); + String ruleXmlWithNoRuleList = generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>"; RuleParser xmlParser = new RuleXmlParser(); @@ -423,16 +452,18 @@ public class RuleXmlParserTest { @Test public void testXmlStream_withNoRuleList() { - String ruleXmlWithNoRuleList = "<R>" - + "<OF>" - + "<C>" + OpenFormula.NOT + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>com.app.test</V>" - + "</AF>" + Map<String, String> atomicFormulaAttrs = new HashMap<>(); + atomicFormulaAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + atomicFormulaAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + atomicFormulaAttrs.put("V", "com.app.test"); + String ruleXmlWithNoRuleList = generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>"; InputStream inputStream = new ByteArrayInputStream(ruleXmlWithNoRuleList.getBytes()); RuleParser xmlParser = new RuleXmlParser(); @@ -442,4 +473,19 @@ public class RuleXmlParserTest { /* expectedExceptionMessageRegex */ "Rules must start with RuleList <RL> tag", () -> xmlParser.parse(inputStream)); } + + private String generateTagWithAttribute(String tag, Map<String, String> attributeValues, + boolean closed) { + StringBuilder res = new StringBuilder("<"); + res.append(tag); + for (String attribute : attributeValues.keySet()) { + res.append(" "); + res.append(attribute); + res.append("=\""); + res.append(attributeValues.get(attribute)); + res.append("\""); + } + res.append(closed ? " />" : ">"); + return res.toString(); + } } diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java index 082fda82499a..a25627155950 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java @@ -36,6 +36,8 @@ import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; @RunWith(JUnit4.class) public class RuleXmlSerializerTest { @@ -58,13 +60,14 @@ public class RuleXmlSerializerTest { new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"), Rule.DENY); RuleSerializer xmlSerializer = new RuleXmlSerializer(); + Map<String, String> packageNameAttrs = new LinkedHashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("V", "com.app.test"); String expectedRules = "<RL>" - + "<R>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<V>com.app.test</V>" - + "</AF>" - + "<E>" + Rule.DENY + "</E>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</R>" + "</RL>"; @@ -81,16 +84,18 @@ public class RuleXmlSerializerTest { "com.app.test"))), Rule.DENY); RuleSerializer xmlSerializer = new RuleXmlSerializer(); OutputStream outputStream = new ByteArrayOutputStream(); + Map<String, String> packageNameAttrs = new LinkedHashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("V", "com.app.test"); String expectedRules = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.NOT + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<V>com.app.test</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; @@ -107,16 +112,18 @@ public class RuleXmlSerializerTest { new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"))), Rule.DENY); RuleSerializer xmlSerializer = new RuleXmlSerializer(); + Map<String, String> packageNameAttrs = new LinkedHashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("V", "com.app.test"); String expectedRules = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.NOT + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<V>com.app.test</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; @@ -133,20 +140,22 @@ public class RuleXmlSerializerTest { new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, "test_cert"))), Rule.DENY); RuleSerializer xmlSerializer = new RuleXmlSerializer(); + Map<String, String> packageNameAttrs = new LinkedHashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("V", "com.app.test"); + Map<String, String> appCertificateAttrs = new LinkedHashMap<>(); + appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE)); + appCertificateAttrs.put("V", "test_cert"); String expectedRules = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.AND + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<V>com.app.test</V>" - + "</AF>" - + "<AF>" - + "<K>" + AtomicFormula.APP_CERTIFICATE + "</K>" - + "<V>test_cert</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.AND)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + + generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; @@ -163,20 +172,22 @@ public class RuleXmlSerializerTest { new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, "test_cert"))), Rule.DENY); RuleSerializer xmlSerializer = new RuleXmlSerializer(); + Map<String, String> packageNameAttrs = new LinkedHashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("V", "com.app.test"); + Map<String, String> appCertificateAttrs = new LinkedHashMap<>(); + appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE)); + appCertificateAttrs.put("V", "test_cert"); String expectedRules = "<RL>" - + "<R>" - + "<OF>" - + "<C>" + OpenFormula.OR + "</C>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<V>com.app.test</V>" - + "</AF>" - + "<AF>" - + "<K>" + AtomicFormula.APP_CERTIFICATE + "</K>" - + "<V>test_cert</V>" - + "</AF>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "OF", + Collections.singletonMap("C", String.valueOf(OpenFormula.OR)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + + generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true) + "</OF>" - + "<E>" + Rule.DENY + "</E>" + "</R>" + "</RL>"; @@ -191,13 +202,14 @@ public class RuleXmlSerializerTest { new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test"), Rule.DENY); RuleSerializer xmlSerializer = new RuleXmlSerializer(); + Map<String, String> packageNameAttrs = new LinkedHashMap<>(); + packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME)); + packageNameAttrs.put("V", "com.app.test"); String expectedRules = "<RL>" - + "<R>" - + "<AF>" - + "<K>" + AtomicFormula.PACKAGE_NAME + "</K>" - + "<V>com.app.test</V>" - + "</AF>" - + "<E>" + Rule.DENY + "</E>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true) + "</R>" + "</RL>"; @@ -212,14 +224,15 @@ public class RuleXmlSerializerTest { new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1), Rule.DENY); RuleSerializer xmlSerializer = new RuleXmlSerializer(); + Map<String, String> versionCodeAttrs = new LinkedHashMap<>(); + versionCodeAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE)); + versionCodeAttrs.put("O", String.valueOf(AtomicFormula.EQ)); + versionCodeAttrs.put("V", "1"); String expectedRules = "<RL>" - + "<R>" - + "<AF>" - + "<K>" + AtomicFormula.VERSION_CODE + "</K>" - + "<O>" + AtomicFormula.EQ + "</O>" - + "<V>1</V>" - + "</AF>" - + "<E>" + Rule.DENY + "</E>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", versionCodeAttrs, /* closed= */ true) + "</R>" + "</RL>"; @@ -234,13 +247,14 @@ public class RuleXmlSerializerTest { new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true), Rule.DENY); RuleSerializer xmlSerializer = new RuleXmlSerializer(); + Map<String, String> preInstalledAttrs = new LinkedHashMap<>(); + preInstalledAttrs.put("K", String.valueOf(AtomicFormula.PRE_INSTALLED)); + preInstalledAttrs.put("V", "true"); String expectedRules = "<RL>" - + "<R>" - + "<AF>" - + "<K>" + AtomicFormula.PRE_INSTALLED + "</K>" - + "<V>true</V>" - + "</AF>" - + "<E>" + Rule.DENY + "</E>" + + generateTagWithAttribute(/* tag= */ "R", + Collections.singletonMap("E", String.valueOf(Rule.DENY)), + /* closed= */ false) + + generateTagWithAttribute(/* tag= */ "AF", preInstalledAttrs, /* closed= */ true) + "</R>" + "</RL>"; @@ -261,6 +275,21 @@ public class RuleXmlSerializerTest { () -> xmlSerializer.serialize(Collections.singletonList(rule))); } + private String generateTagWithAttribute(String tag, Map<String, String> attributeValues, + boolean closed) { + StringBuilder res = new StringBuilder("<"); + res.append(tag); + for (String attribute : attributeValues.keySet()) { + res.append(" "); + res.append(attribute); + res.append("=\""); + res.append(attributeValues.get(attribute)); + res.append("\""); + } + res.append(closed ? " />" : ">"); + return res.toString(); + } + private Formula getInvalidFormula() { return new Formula() { @Override |