Improved missing ping, fixed fortify issue

This commit is contained in:
anhefti 2020-01-07 16:07:14 +01:00
parent 67c1aef81e
commit d8668e1c68
10 changed files with 71 additions and 26 deletions

13
pom.xml
View file

@ -262,10 +262,10 @@
</dependency>
<!-- JMX -->
<!-- <dependency> -->
<!-- <groupId>org.jolokia</groupId> -->
<!-- <artifactId>jolokia-core</artifactId> -->
<!-- </dependency> -->
<!-- <dependency> -->
<!-- <groupId>org.jolokia</groupId> -->
<!-- <artifactId>jolokia-core</artifactId> -->
<!-- </dependency> -->
<!-- Apache HTTP -->
<dependency>
@ -303,6 +303,11 @@
<artifactId>jncryptor</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.8</version>
</dependency>
<!-- Testing -->

View file

@ -183,7 +183,7 @@ public class ClientHttpRequestFactoryService {
.toCharArray();
if (password.length < 3) {
log.error("Missing or incorrect trust-store password: " + String.valueOf(password));
log.error("Missing or incorrect trust-store password");
throw new IllegalArgumentException("Missing or incorrect trust-store password");
}

View file

@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gbl.api;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
@ -29,6 +30,7 @@ public class JSONMapper extends ObjectMapper {
super.configure(
com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_WITH_ZONE_ID,
false);
super.setSerializationInclusion(Include.NON_NULL);
}
}

View file

@ -16,8 +16,6 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
import ch.ethz.seb.sebserver.gbl.util.Utils;
public class ClientConnectionData {
@ -26,31 +24,32 @@ public class ClientConnectionData {
public final ClientConnection clientConnection;
@JsonProperty("indicatorValues")
public final List<? extends IndicatorValue> indicatorValues;
@JsonIgnore
public final boolean missingPing;
public final Boolean missingPing;
@JsonCreator
protected ClientConnectionData(
public ClientConnectionData(
@JsonProperty("missingPing") final Boolean missingPing,
@JsonProperty("clientConnection") final ClientConnection clientConnection,
@JsonProperty("indicatorValues") final Collection<? extends SimpleIndicatorValue> indicatorValues) {
this.missingPing = missingPing;
this.clientConnection = clientConnection;
this.indicatorValues = Utils.immutableListOf(indicatorValues);
this.missingPing = clientConnection.status == ConnectionStatus.ACTIVE &&
this.indicatorValues.stream()
.filter(ind -> ind.getType() == IndicatorType.LAST_PING)
.findFirst()
.map(ind -> (long) ind.getValue())
.orElse(0L) > 5000;
}
protected ClientConnectionData(
@JsonProperty("clientConnection") final ClientConnection clientConnection,
@JsonProperty("indicatorValues") final List<? extends IndicatorValue> indicatorValues) {
final ClientConnection clientConnection,
final List<? extends IndicatorValue> indicatorValues) {
this.missingPing = null;
this.clientConnection = clientConnection;
this.indicatorValues = Utils.immutableListOf(indicatorValues);
this.missingPing = false;
}
@JsonProperty("missingPing")
public Boolean getMissingPing() {
return this.missingPing;
}
@JsonIgnore

View file

@ -28,6 +28,7 @@ import java.util.stream.Collector;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.eclipse.swt.graphics.RGB;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
@ -375,6 +376,13 @@ public final class Utils {
return builder.toString();
}
public static String escapeHTML_XML_EcmaScript(final String string) {
return StringEscapeUtils.escapeXml11(
StringEscapeUtils.escapeHtml4(
StringEscapeUtils.escapeEcmaScript(string)));
}
// https://www.owasp.org/index.php/HTTP_Response_Splitting
public static String preventResponseSplittingAttack(final String string) {
final int xni = string.indexOf('\n');
final int xri = string.indexOf('\r');

View file

@ -61,8 +61,9 @@ public abstract class AbstractDownloadServiceHandler implements DownloadServiceH
downloadFileName);
}
final String header =
"attachment; filename=\"" + Utils.preventResponseSplittingAttack(downloadFileName) + "\"";
final String header = "attachment; filename=\"" +
Utils.escapeHTML_XML_EcmaScript(Utils.preventResponseSplittingAttack(downloadFileName)) +
"\"";
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, header);
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);

View file

@ -14,6 +14,8 @@ import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
@ -61,4 +63,10 @@ public class ClientConnectionDataInternal extends ClientConnectionData {
return this.indicatorMapping.get(eventType);
}
@Override
@JsonProperty("missingPing")
public Boolean getMissingPing() {
return this.pingIndicator.missingPing;
}
}

View file

@ -36,8 +36,8 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
private static final Logger log = LoggerFactory.getLogger(PingIntervalClientIndicator.class);
private long pingErrorThreshold;
private boolean isOnError = false;
long pingErrorThreshold;
boolean missingPing = false;
boolean hidden = false;
@ -84,9 +84,9 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
public ClientEventRecord updateLogEvent() {
final long now = DateTime.now(DateTimeZone.UTC).getMillis();
final long value = now - (long) super.currentValue;
if (this.isOnError) {
if (this.missingPing) {
if (this.pingErrorThreshold > value) {
this.isOnError = false;
this.missingPing = false;
return new ClientEventRecord(
null,
this.connectionId,
@ -98,7 +98,7 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
}
} else {
if (this.pingErrorThreshold < value) {
this.isOnError = true;
this.missingPing = true;
return new ClientEventRecord(
null,
this.connectionId,

View file

@ -13,6 +13,7 @@ import java.util.Objects;
import java.util.UUID;
import java.util.function.Predicate;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -25,6 +26,7 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
@ -385,6 +387,17 @@ public class SebClientConnectionServiceImpl implements SebClientConnectionServic
@Override
public Result<ClientConnection> disableConnection(final String connectionToken, final Long institutionId) {
return Result.tryCatch(() -> {
final ClientConnectionData connectionData = getExamSessionService()
.getConnectionData(connectionToken)
.getOrThrow();
// An active connection can only be disabled if we have a missing ping
if (connectionData.clientConnection.status == ConnectionStatus.ACTIVE &&
!BooleanUtils.isTrue(connectionData.getMissingPing())) {
return connectionData.clientConnection;
}
if (log.isDebugEnabled()) {
log.debug("SEB client connection: SEB Server disable attempt for "
+ "instituion {} "

View file

@ -62,4 +62,13 @@ public class InstitutionTest {
json);
}
@Test
public void testNullValues() throws Exception {
final JSONMapper jsonMapper = new JSONMapper();
final Institution inst = new Institution(1L, null, "suffix", "logo", "theme", null);
final String jsonString = jsonMapper.writeValueAsString(inst);
assertEquals("{\"id\":1,\"urlSuffix\":\"suffix\",\"logoImage\":\"logo\",\"themeName\":\"theme\"}", jsonString);
}
}