Improved missing ping, fixed fortify issue
This commit is contained in:
		
							parent
							
								
									67c1aef81e
								
							
						
					
					
						commit
						d8668e1c68
					
				
					 10 changed files with 71 additions and 26 deletions
				
			
		
							
								
								
									
										13
									
								
								pom.xml
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								pom.xml
									
										
									
									
									
								
							|  | @ -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 --> | ||||
|  |  | |||
|  | @ -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"); | ||||
|             } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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'); | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
|  | @ -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 {} " | ||||
|  |  | |||
|  | @ -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); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti