diff --git a/OCPP-J/src/main/java/eu/chargetime/ocpp/Draft_HttpHealthCheck.java b/OCPP-J/src/main/java/eu/chargetime/ocpp/Draft_HttpHealthCheck.java index a148f5de9..7d199ab35 100644 --- a/OCPP-J/src/main/java/eu/chargetime/ocpp/Draft_HttpHealthCheck.java +++ b/OCPP-J/src/main/java/eu/chargetime/ocpp/Draft_HttpHealthCheck.java @@ -22,7 +22,7 @@ class Draft_HttpHealthCheck extends Draft { static Boolean isHttp(ClientHandshake handshakedata) { String upgradeField = handshakedata.getFieldValue("Upgrade"); - return upgradeField == null || upgradeField == ""; + return upgradeField == null || upgradeField.isEmpty(); } @Override diff --git a/OCPP-J/src/main/java/eu/chargetime/ocpp/WebSocketListener.java b/OCPP-J/src/main/java/eu/chargetime/ocpp/WebSocketListener.java index 5eb06e667..763015161 100644 --- a/OCPP-J/src/main/java/eu/chargetime/ocpp/WebSocketListener.java +++ b/OCPP-J/src/main/java/eu/chargetime/ocpp/WebSocketListener.java @@ -271,7 +271,11 @@ public void close() { server.stop(); } catch (InterruptedException ex) { logger.error("Failed to close listener", ex); + // restore thread interrupted state + Thread.currentThread().interrupt(); } + // restore thread interrupted state + Thread.currentThread().interrupt(); } finally { closed = true; server = null; diff --git a/ocpp-common/src/main/java/eu/chargetime/ocpp/Communicator.java b/ocpp-common/src/main/java/eu/chargetime/ocpp/Communicator.java index 3422f5769..ad9995cae 100644 --- a/ocpp-common/src/main/java/eu/chargetime/ocpp/Communicator.java +++ b/ocpp-common/src/main/java/eu/chargetime/ocpp/Communicator.java @@ -363,6 +363,10 @@ public void run() { Thread.sleep(DELAY_IN_MILLISECONDS); if (!hasFailed()) popRetryMessage(); } + } catch (InterruptedException ex) { + logger.warn("RetryRunner::run() interrupted", ex); + // restore thread interrupted state + Thread.currentThread().interrupt(); } catch (Exception ex) { logger.warn("RetryRunner::run() failed", ex); } diff --git a/ocpp-common/src/main/java/eu/chargetime/ocpp/utilities/SugarUtil.java b/ocpp-common/src/main/java/eu/chargetime/ocpp/utilities/SugarUtil.java index 598334d78..9ab534175 100644 --- a/ocpp-common/src/main/java/eu/chargetime/ocpp/utilities/SugarUtil.java +++ b/ocpp-common/src/main/java/eu/chargetime/ocpp/utilities/SugarUtil.java @@ -31,6 +31,7 @@ of this software and associated documentation files (the "Software"), to deal import java.io.IOException; import java.io.StringWriter; import java.time.ZonedDateTime; +import javax.xml.XMLConstants; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPMessage; import javax.xml.transform.Transformer; @@ -50,6 +51,9 @@ public static String docToString(Document doc) { try { StringWriter sw = new StringWriter(); TransformerFactory tf = TransformerFactory.newInstance(); + // disable access to external entities to prevent XXE attacks + tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); Transformer transformer = tf.newTransformer(); transformer.transform(new DOMSource(doc), new StreamResult(sw)); return sw.toString(); diff --git a/ocpp-v1_6-example/json-client-implementation/pom.xml b/ocpp-v1_6-example/json-client-implementation/pom.xml index c4b9e15b5..5d918d8ad 100644 --- a/ocpp-v1_6-example/json-client-implementation/pom.xml +++ b/ocpp-v1_6-example/json-client-implementation/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.5.6 + 3.2.0 eu.chargetime.ocpp diff --git a/ocpp-v1_6-example/json-client-implementation/src/test/java/eu/chargetime/ocpp/jsonclientimplementation/ocpphandler/OCPPHandlerTest.java b/ocpp-v1_6-example/json-client-implementation/src/test/java/eu/chargetime/ocpp/jsonclientimplementation/ocpphandler/OCPPHandlerTest.java index 97ea1c02a..16b13ef34 100644 --- a/ocpp-v1_6-example/json-client-implementation/src/test/java/eu/chargetime/ocpp/jsonclientimplementation/ocpphandler/OCPPHandlerTest.java +++ b/ocpp-v1_6-example/json-client-implementation/src/test/java/eu/chargetime/ocpp/jsonclientimplementation/ocpphandler/OCPPHandlerTest.java @@ -47,8 +47,13 @@ public void testOCPPAuthorizeHandler() { .toCompletableFuture().get(); assertTrue(true); assertEquals(AuthorizationStatus.Accepted,authorizeConfirmation.getIdTagInfo().getStatus()); - } catch (OccurenceConstraintException | UnsupportedFeatureException - | ExecutionException | InterruptedException e) { + } catch (InterruptedException e) { + log.error("Thread interrupted: " + e); + // restore thread interrupted state + Thread.currentThread().interrupt(); + log.error("Test will fail"); + assertTrue(false); + } catch (OccurenceConstraintException | UnsupportedFeatureException | ExecutionException e) { log.error("Exception occurred: " + e); log.error("Test will fail"); assertTrue(false); diff --git a/ocpp-v1_6-example/json_server_example/pom.xml b/ocpp-v1_6-example/json_server_example/pom.xml index 1d3c6ec93..9b13eef31 100644 --- a/ocpp-v1_6-example/json_server_example/pom.xml +++ b/ocpp-v1_6-example/json_server_example/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.5.6 + 3.2.0 eu.chargetime.ocpp diff --git a/ocpp-v1_6-test/src/main/java/eu/chargetime/ocpp/test/SOAPTestClient.java b/ocpp-v1_6-test/src/main/java/eu/chargetime/ocpp/test/SOAPTestClient.java index 41fda3ceb..a4a7ce4af 100644 --- a/ocpp-v1_6-test/src/main/java/eu/chargetime/ocpp/test/SOAPTestClient.java +++ b/ocpp-v1_6-test/src/main/java/eu/chargetime/ocpp/test/SOAPTestClient.java @@ -143,7 +143,9 @@ private void openWS() { try { soapMessage = transmitter.relay(message.getMessage()).get(); } catch (InterruptedException e) { - logger.warn("openWS() transmitter.relay failed", e); + logger.warn("openWS() transmitter.relay interrupted", e); + // restore thread interrupted state + Thread.currentThread().interrupt(); } catch (ExecutionException e) { logger.warn("openWS() transmitter.relay failed", e); } diff --git a/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/SOAPClient.java b/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/SOAPClient.java index f0a34c832..b373590fd 100644 --- a/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/SOAPClient.java +++ b/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/SOAPClient.java @@ -150,7 +150,9 @@ private void openWS() { try { soapMessage = transmitter.relay(message.getMessage()).get(); } catch (InterruptedException e) { - logger.warn("openWS() transmitter.relay failed", e); + logger.warn("openWS() transmitter.relay interrupted", e); + // restore thread interrupted state + Thread.currentThread().interrupt(); } catch (ExecutionException e) { logger.warn("openWS() transmitter.relay failed", e); } diff --git a/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/WebServiceListener.java b/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/WebServiceListener.java index d37dfe065..d14f7f460 100644 --- a/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/WebServiceListener.java +++ b/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/WebServiceListener.java @@ -146,7 +146,11 @@ public void timeout() { SOAPMessage confirmation = null; try { confirmation = chargeBoxes.get(identity).relay(message).get(); - } catch (InterruptedException | ExecutionException e) { + } catch (InterruptedException e) { + logger.warn("incomingRequest() chargeBoxes.relay interrupted", e); + // restore thread interrupted state + Thread.currentThread().interrupt(); + } catch (ExecutionException e) { logger.warn("incomingRequest() chargeBoxes.relay failed", e); } diff --git a/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/model/validation/IdentifierStringValidationRule.java b/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/model/validation/IdentifierStringValidationRule.java index 241d07034..fcfbf6853 100644 --- a/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/model/validation/IdentifierStringValidationRule.java +++ b/ocpp-v1_6/src/main/java/eu/chargetime/ocpp/model/validation/IdentifierStringValidationRule.java @@ -31,7 +31,7 @@ of this software and associated documentation files (the "Software"), to deal public class IdentifierStringValidationRule implements IValidationRule { private final String ERROR_MESSAGE = "Illegal character(s) in IdentifierString."; - private final String PATTERN = "([a-zA-Z0-9]|\\*|\\-|\\_|\\=|\\:|\\+|\\||\\@|\\.)+"; + private final String PATTERN = "^[\\w\\Q*-=:+|@.\\E]{0,255}$"; @Override public void validate(String value) throws PropertyConstraintException { diff --git a/ocpp-v1_6/src/test/java/eu/chargetime/ocpp/test/SOAPCommunicatorTest.java b/ocpp-v1_6/src/test/java/eu/chargetime/ocpp/test/SOAPCommunicatorTest.java index 05e2b3e5a..29c2c6eca 100644 --- a/ocpp-v1_6/src/test/java/eu/chargetime/ocpp/test/SOAPCommunicatorTest.java +++ b/ocpp-v1_6/src/test/java/eu/chargetime/ocpp/test/SOAPCommunicatorTest.java @@ -14,6 +14,7 @@ import java.io.StringWriter; import java.time.ZonedDateTime; import java.util.Locale; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; @@ -69,6 +70,9 @@ public static String docToString(Document doc) { try { StringWriter sw = new StringWriter(); TransformerFactory tf = TransformerFactory.newInstance(); + // disable access to external entities to prevent XXE attacks + tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); Transformer transformer = tf.newTransformer(); transformer.transform(new DOMSource(doc), new StreamResult(sw)); return sw.toString(); @@ -79,6 +83,10 @@ public static String docToString(Document doc) { public static Document stringToDocument(String xml) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + // disable access to external entities to prevent XXE attacks + factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + factory.setExpandEntityReferences(false); factory.setNamespaceAware(true); DocumentBuilder db = factory.newDocumentBuilder(); diff --git a/ocpp-v2-test/src/test/java/eu/chargetime/ocpp/test/OCPP201MultiProtocolIntegrationTest.java b/ocpp-v2-test/src/test/java/eu/chargetime/ocpp/test/OCPP201MultiProtocolIntegrationTest.java index e2a2f0635..944a2b8b4 100644 --- a/ocpp-v2-test/src/test/java/eu/chargetime/ocpp/test/OCPP201MultiProtocolIntegrationTest.java +++ b/ocpp-v2-test/src/test/java/eu/chargetime/ocpp/test/OCPP201MultiProtocolIntegrationTest.java @@ -74,6 +74,8 @@ private FakeCSMS setupAndStartCSMS(List protocolVersions) { try { Thread.sleep(100); } catch (InterruptedException e) { + // restore thread interrupted state + Thread.currentThread().interrupt(); throw new RuntimeException(e); } assertThat(csms.getPort(), not(0)); diff --git a/ocpp-v2/src/main/java/eu/chargetime/ocpp/MultiProtocolWebSocketListener.java b/ocpp-v2/src/main/java/eu/chargetime/ocpp/MultiProtocolWebSocketListener.java index 47c37fe45..314e993a4 100644 --- a/ocpp-v2/src/main/java/eu/chargetime/ocpp/MultiProtocolWebSocketListener.java +++ b/ocpp-v2/src/main/java/eu/chargetime/ocpp/MultiProtocolWebSocketListener.java @@ -300,7 +300,11 @@ public void close() { server.stop(); } catch (InterruptedException ex) { logger.error("Failed to close listener", ex); + // restore thread interrupted state + Thread.currentThread().interrupt(); } + // restore thread interrupted state + Thread.currentThread().interrupt(); } finally { closed = true; server = null; diff --git a/ocpp-v2_0/src/main/java/eu/chargetime/ocpp/model/validation/IdentifierStringValidationRule.java b/ocpp-v2_0/src/main/java/eu/chargetime/ocpp/model/validation/IdentifierStringValidationRule.java index 15bb0b10f..747e5d294 100644 --- a/ocpp-v2_0/src/main/java/eu/chargetime/ocpp/model/validation/IdentifierStringValidationRule.java +++ b/ocpp-v2_0/src/main/java/eu/chargetime/ocpp/model/validation/IdentifierStringValidationRule.java @@ -30,7 +30,7 @@ of this software and associated documentation files (the "Software"), to deal public class IdentifierStringValidationRule implements IValidationRule { private final String ERROR_MESSAGE = "Illegal character(s) in IdentifierString."; - private final String PATTERN = "([a-zA-Z0-9]|\\*|\\-|\\_|\\=|\\:|\\+|\\||\\@|\\.)+"; + private final String PATTERN = "^[\\w\\Q*-=:+|@.\\E]{0,255}$"; @Override public void validate(String value) throws PropertyConstraintException {