feat: add user, system certificate in existing network security config (#3724)

* add user, system certificate in existing network security config rather than creating a fresh config

* prevent deleting existing network security config to modify the existing one

* modified test case for certificate check.

Rather than comparing exact string, parse and check if user and system certificate exist
This commit is contained in:
Sawan Garg 2024-11-17 06:02:24 +05:30 committed by GitHub
parent c2eab3101c
commit 1eb1daf12a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 78 additions and 38 deletions

View File

@ -343,12 +343,6 @@ public class ApkBuilder {
}
File netSecConfOrig = new File(mApkDir, "res/xml/network_security_config.xml");
if (netSecConfOrig.exists()) {
LOGGER.info("Replacing existing network_security_config.xml!");
//noinspection ResultOfMethodCallIgnored
netSecConfOrig.delete();
}
ResXmlPatcher.modNetworkSecurityConfig(netSecConfOrig);
ResXmlPatcher.setNetworkSecurityConfig(manifest);
LOGGER.info("Added permissive network security config in manifest");

View File

@ -146,30 +146,59 @@ public final class ResXmlPatcher {
*/
public static void modNetworkSecurityConfig(File file)
throws ParserConfigurationException, TransformerException, IOException, SAXException {
DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
Document document;
if (file.exists()) {
document = documentBuilder.parse(file);
document.getDocumentElement().normalize();
} else {
document = documentBuilder.newDocument();
}
Element root = (Element) document.getElementsByTagName("network-security-config").item(0);
if (root == null) {
root = document.createElement("network-security-config");
document.appendChild(root);
}
Element baseConfig = (Element) document.getElementsByTagName("base-config").item(0);
if (baseConfig == null) {
baseConfig = document.createElement("base-config");
root.appendChild(baseConfig);
}
Element root = document.createElement("network-security-config");
document.appendChild(root);
Element baseConfig = document.createElement("base-config");
root.appendChild(baseConfig);
Element trustAnchors = document.createElement("trust-anchors");
baseConfig.appendChild(trustAnchors);
Element trustAnchors = (Element) document.getElementsByTagName("trust-anchors").item(0);
if (trustAnchors == null) {
trustAnchors = document.createElement("trust-anchors");
baseConfig.appendChild(trustAnchors);
}
Element certSystem = document.createElement("certificates");
Attr attrSystem = document.createAttribute("src");
attrSystem.setValue("system");
certSystem.setAttributeNode(attrSystem);
trustAnchors.appendChild(certSystem);
Element certUser = document.createElement("certificates");
Attr attrUser = document.createAttribute("src");
attrUser.setValue("user");
certUser.setAttributeNode(attrUser);
trustAnchors.appendChild(certUser);
NodeList certificates = document.getElementsByTagName("certificates");
boolean hasSystemCert = false;
boolean hasUserCert = false;
for (int i = 0; i < certificates.getLength(); i++) {
Element cert = (Element) certificates.item(i);
String src = cert.getAttribute("src");
if ("system".equals(src)) {
hasSystemCert = true;
} else if ("user".equals(src)) {
hasUserCert = true;
}
}
if (!hasSystemCert) {
Element certSystem = document.createElement("certificates");
certSystem.setAttribute("src", "system");
trustAnchors.appendChild(certSystem);
}
if (!hasUserCert) {
Element certUser = document.createElement("certificates");
certUser.setAttribute("src", "user");
trustAnchors.appendChild(certUser);
}
saveDocument(file, document);
}

View File

@ -17,25 +17,31 @@
package brut.androlib.aapt2;
import brut.androlib.*;
import brut.androlib.Config;
import brut.common.BrutException;
import brut.directory.ExtFile;
import brut.util.OS;
import org.custommonkey.xmlunit.XMLUnit;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
import static org.junit.Assert.*;
public class NetworkConfigTest extends BaseTest {
@ -72,20 +78,31 @@ public class NetworkConfigTest extends BaseTest {
}
@Test
public void netSecConfGeneric() throws IOException, SAXException {
LOGGER.info("Comparing network security configuration file...");
String expected = TestUtils.replaceNewlines("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" +
"<network-security-config><base-config><trust-anchors><certificates src=\"system\"/><certificates src=\"us" +
"er\"/></trust-anchors></base-config></network-security-config>");
public void netSecConfGeneric() throws IOException, SAXException, ParserConfigurationException, XPathExpressionException {
LOGGER.info("Verifying network security configuration file contains user and system certificates...");
byte[] encoded = Files.readAllBytes(Paths.get(String.valueOf(sTestNewDir), "res/xml/network_security_config.xml"));
String obtained = TestUtils.replaceNewlines(new String(encoded));
String obtained = new String(encoded);
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreAttributeOrder(true);
XMLUnit.setCompareUnmatched(false);
// Load the XML document
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new ByteArrayInputStream(obtained.getBytes()));
assertXMLEqual(expected, obtained);
// XPath expression to check for user and system certificates
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xpath = xPathFactory.newXPath();
// Check if 'system' certificate exists
XPathExpression systemCertExpr = xpath.compile("//certificates[@src='system']");
NodeList systemCertNodes = (NodeList) systemCertExpr.evaluate(document, XPathConstants.NODESET);
assertTrue(systemCertNodes.getLength() > 0);
// Check if 'user' certificate exists
XPathExpression userCertExpr = xpath.compile("//certificates[@src='user']");
NodeList userCertNodes = (NodeList) userCertExpr.evaluate(document, XPathConstants.NODESET);
assertTrue(userCertNodes.getLength() > 0);
}
@Test