Skip to content

Commit 28d6652

Browse files
authored
Merge pull request #715 from tls-attacker/ConfigGeneration
Configuration features and fixes
2 parents ef3f833 + 1f7b334 commit 28d6652

38 files changed

+6707
-1523
lines changed

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/config/Config.java

Lines changed: 93 additions & 17 deletions
Large diffs are not rendered by default.

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/config/ConfigIO.java

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,51 @@
1111
package de.rub.nds.tlsattacker.core.config;
1212

1313
import de.rub.nds.tlsattacker.core.config.filter.ConfigDisplayFilter;
14+
import de.rub.nds.tlsattacker.core.workflow.WorkflowTrace;
15+
import de.rub.nds.tlsattacker.core.workflow.WorkflowTraceSerializer;
1416
import java.io.ByteArrayInputStream;
1517
import java.io.ByteArrayOutputStream;
1618
import java.io.File;
19+
import java.io.FileInputStream;
1720
import java.io.FileNotFoundException;
1821
import java.io.FileOutputStream;
1922
import java.io.IOException;
2023
import java.io.InputStream;
2124
import java.io.OutputStream;
25+
import javax.xml.XMLConstants;
26+
import javax.xml.bind.DataBindingException;
2227
import javax.xml.bind.JAXB;
23-
import javax.xml.parsers.ParserConfigurationException;
24-
import javax.xml.transform.TransformerException;
25-
import javax.xml.xpath.XPathExpressionException;
28+
import javax.xml.bind.JAXBContext;
29+
import javax.xml.bind.JAXBException;
30+
import javax.xml.bind.Unmarshaller;
31+
import javax.xml.bind.ValidationEvent;
32+
import javax.xml.bind.ValidationEventHandler;
33+
import javax.xml.stream.XMLInputFactory;
34+
import javax.xml.stream.XMLStreamException;
35+
import javax.xml.stream.XMLStreamReader;
36+
import javax.xml.transform.stream.StreamSource;
37+
import javax.xml.validation.Schema;
38+
import javax.xml.validation.SchemaFactory;
39+
import org.apache.logging.log4j.LogManager;
40+
import org.apache.logging.log4j.Logger;
2641
import org.xml.sax.SAXException;
2742

2843
public class ConfigIO {
2944

45+
private static final Logger LOGGER = LogManager.getLogger();
46+
47+
/**
48+
* context initialization is expensive, we need to do that only once
49+
*/
50+
private static JAXBContext context;
51+
52+
static synchronized JAXBContext getJAXBContext() throws JAXBException {
53+
if (context == null) {
54+
context = JAXBContext.newInstance(Config.class);
55+
}
56+
return context;
57+
}
58+
3059
public static void write(Config config, File f) {
3160
try {
3261
write(config, new FileOutputStream(f));
@@ -59,13 +88,70 @@ public static void write(Config config, OutputStream os, ConfigDisplayFilter fil
5988
}
6089

6190
public static Config read(File f) {
62-
Config config = JAXB.unmarshal(f, Config.class);
63-
return config;
91+
try {
92+
Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
93+
// output any anomalies in the given config file
94+
unmarshaller.setEventHandler(new ValidationEventHandler() {
95+
@Override
96+
public boolean handleEvent(ValidationEvent event) {
97+
// Raise an exception also on warnings
98+
return false;
99+
}
100+
});
101+
return read(new FileInputStream(f), unmarshaller);
102+
} catch (JAXBException e) {
103+
throw new RuntimeException(e);
104+
} catch (FileNotFoundException e) {
105+
throw new IllegalArgumentException("File cannot be found");
106+
}
64107
}
65108

66109
public static Config read(InputStream stream) {
67-
Config config = JAXB.unmarshal(stream, Config.class);
68-
return config;
110+
try {
111+
Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
112+
// output any anomalies in the given config file
113+
unmarshaller.setEventHandler(new ValidationEventHandler() {
114+
@Override
115+
public boolean handleEvent(ValidationEvent event) {
116+
// Raise an exception also on warnings
117+
return false;
118+
}
119+
});
120+
return read(stream, unmarshaller);
121+
} catch (JAXBException e) {
122+
throw new RuntimeException(e);
123+
}
124+
}
125+
126+
/**
127+
* Reads the XML from the given inputStream with the provided unmarshaller into a new Config
128+
*
129+
* @param stream
130+
* The stream that provides the XML structure
131+
* @param unmarshaller
132+
* The unmarshaller that will be used during the parsing
133+
* @return Config a new Config that contains the parsed values from the inputStream
134+
*/
135+
private static Config read(InputStream stream, Unmarshaller unmarshaller) {
136+
if (stream == null) {
137+
throw new IllegalArgumentException("Stream cannot be null");
138+
}
139+
try {
140+
String xsd_source = ConfigSchemaGenerator.AccumulatingSchemaOutputResolver.mapSystemIds();
141+
XMLInputFactory xif = XMLInputFactory.newFactory();
142+
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
143+
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
144+
XMLStreamReader xsr = xif.createXMLStreamReader(stream);
145+
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
146+
Schema configSchema =
147+
sf.newSchema(new StreamSource(WorkflowTraceSerializer.class.getResourceAsStream("/" + xsd_source)));
148+
configSchema.newValidator();
149+
unmarshaller.setSchema(configSchema);
150+
Config config = (Config) unmarshaller.unmarshal(xsr);
151+
return config;
152+
} catch (XMLStreamException | SAXException | JAXBException e) {
153+
throw new RuntimeException(e);
154+
}
69155
}
70156

71157
public static Config copy(Config config) {
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
3+
*
4+
* Copyright 2014-2020 Ruhr University Bochum, Paderborn University,
5+
* and Hackmanit GmbH
6+
*
7+
* Licensed under Apache License 2.0
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*/
10+
11+
package de.rub.nds.tlsattacker.core.config;
12+
13+
import de.rub.nds.tlsattacker.core.workflow.WorkflowTraceSchemaGenerator;
14+
import de.rub.nds.tlsattacker.core.workflow.WorkflowTraceSerializer;
15+
import java.io.File;
16+
import java.io.FileWriter;
17+
import java.io.IOException;
18+
import java.io.StringWriter;
19+
import java.util.HashMap;
20+
import java.util.Map;
21+
import javax.xml.bind.JAXBException;
22+
import javax.xml.bind.SchemaOutputResolver;
23+
import javax.xml.transform.Result;
24+
import javax.xml.transform.stream.StreamResult;
25+
import org.apache.commons.lang3.StringUtils;
26+
27+
/**
28+
*
29+
* @author ic0ns
30+
* @author JonSnowWhite
31+
*/
32+
public class ConfigSchemaGenerator {
33+
34+
private static final String ROOT_NS = "";
35+
36+
private static final String NO_NS = "__NO__NS";
37+
38+
public static void main(String[] args) {
39+
try {
40+
new File(args[0]).mkdirs();
41+
generateSchema(args[0]);
42+
} catch (IOException | JAXBException e) {
43+
e.printStackTrace();
44+
}
45+
}
46+
47+
private static void generateSchema(String path) throws IOException, JAXBException {
48+
AccumulatingSchemaOutputResolver sor = new AccumulatingSchemaOutputResolver();
49+
ConfigIO.getJAXBContext().generateSchema(sor);
50+
for (Map.Entry<String, StringWriter> e : sor.getSchemaWriters().entrySet()) {
51+
String systemId = sor.getSystemIds().get(e.getKey());
52+
FileWriter w = null;
53+
try {
54+
File f = new File(path, systemId);
55+
w = new FileWriter(f);
56+
System.out.println(String.format("Writing %s to %s", e.getKey(), f.getAbsolutePath()));
57+
w.write(e.getValue().toString());
58+
} finally {
59+
if (w != null) {
60+
w.close();
61+
}
62+
}
63+
}
64+
}
65+
66+
public static class AccumulatingSchemaOutputResolver extends SchemaOutputResolver {
67+
68+
private final Map<String, StringWriter> schemaWriters = new HashMap<>();
69+
private final Map<String, String> systemIds = new HashMap<>();
70+
71+
public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
72+
String ns = StringUtils.isBlank(namespaceURI) ? NO_NS : namespaceURI;
73+
schemaWriters.put(ns, new StringWriter());
74+
String systemId = mapSystemIds();
75+
systemIds.put(ns, systemId);
76+
StreamResult result = new StreamResult(schemaWriters.get(ns));
77+
result.setSystemId(systemId);
78+
return result;
79+
}
80+
81+
public static String mapSystemIds() {
82+
return "Config.xsd";
83+
}
84+
85+
public Map<String, StringWriter> getSchemaWriters() {
86+
return schemaWriters;
87+
}
88+
89+
public Map<String, String> getSystemIds() {
90+
return systemIds;
91+
}
92+
}
93+
}

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/workflow/WorkflowTraceSchemaGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,14 @@ public static class AccumulatingSchemaOutputResolver extends SchemaOutputResolve
6565
public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
6666
String ns = StringUtils.isBlank(namespaceURI) ? NO_NS : namespaceURI;
6767
schemaWriters.put(ns, new StringWriter());
68-
String systemId = mapSystemIds(ns, suggestedFileName);
68+
String systemId = mapSystemIds();
6969
systemIds.put(ns, systemId);
7070
StreamResult result = new StreamResult(schemaWriters.get(ns));
7171
result.setSystemId(systemId);
7272
return result;
7373
}
7474

75-
private static String mapSystemIds(String ns, String suggestedFileName) {
75+
public static String mapSystemIds() {
7676
return "workflowTrace.xsd";
7777
}
7878

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/workflow/WorkflowTraceSerializer.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import javax.xml.bind.JAXBException;
2828
import javax.xml.bind.Marshaller;
2929
import javax.xml.bind.Unmarshaller;
30+
import javax.xml.bind.ValidationEvent;
31+
import javax.xml.bind.ValidationEventHandler;
3032
import javax.xml.stream.XMLInputFactory;
3133
import javax.xml.stream.XMLStreamException;
3234
import javax.xml.stream.XMLStreamReader;
@@ -145,18 +147,27 @@ public static void write(OutputStream outputStream, WorkflowTrace workflowTrace)
145147
public static WorkflowTrace read(InputStream inputStream) throws JAXBException, IOException, XMLStreamException {
146148
try {
147149
context = getJAXBContext();
148-
Unmarshaller m = context.createUnmarshaller();
150+
Unmarshaller unmarshaller = context.createUnmarshaller();
149151

152+
unmarshaller.setEventHandler(new ValidationEventHandler() {
153+
@Override
154+
public boolean handleEvent(ValidationEvent event) {
155+
// raise an Exception also on Warnings
156+
return false;
157+
}
158+
});
159+
160+
String xsd_source = WorkflowTraceSchemaGenerator.AccumulatingSchemaOutputResolver.mapSystemIds();
150161
XMLInputFactory xif = XMLInputFactory.newFactory();
151162
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
152163
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
153164
XMLStreamReader xsr = xif.createXMLStreamReader(inputStream);
154165
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
155166
Schema workflowTraceSchema =
156-
sf.newSchema(new StreamSource(WorkflowTraceSerializer.class.getResourceAsStream("/workflowTrace.xsd")));
167+
sf.newSchema(new StreamSource(WorkflowTraceSerializer.class.getResourceAsStream("/" + xsd_source)));
157168
workflowTraceSchema.newValidator();
158-
m.setSchema(workflowTraceSchema);
159-
WorkflowTrace wt = (WorkflowTrace) m.unmarshal(xsr);
169+
unmarshaller.setSchema(workflowTraceSchema);
170+
WorkflowTrace wt = (WorkflowTrace) unmarshaller.unmarshal(xsr);
160171
inputStream.close();
161172
return wt;
162173
} catch (SAXException ex) {

0 commit comments

Comments
 (0)