/**
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
*
* Copyright 2014-2016 Ruhr University Bochum / Hackmanit GmbH
*
* Licensed under Apache License 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*/
package de.rub.nds.tlsattacker.tls.protocol;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
import de.rub.nds.tlsattacker.dtls.record.DtlsRecord;
import de.rub.nds.tlsattacker.modifiablevariable.ModifiableVariableFactory;
import de.rub.nds.tlsattacker.modifiablevariable.ModifiableVariableProperty;
import de.rub.nds.tlsattacker.modifiablevariable.bytearray.ModifiableByteArray;
import de.rub.nds.tlsattacker.tls.constants.ConnectionEnd;
import de.rub.nds.tlsattacker.tls.constants.ProtocolMessageType;
import de.rub.nds.tlsattacker.tls.record.Record;
import de.rub.nds.tlsattacker.tls.workflow.TlsContext;
import de.rub.nds.tlsattacker.util.RandomHelper;
/**
* TLS Protocol message is the message included in the Record message.
*
* @author juraj
* @author Philip Riese <philip.riese@rub.de>
*/
@XmlRootElement
public abstract class ProtocolMessage extends ModifiableVariableHolder implements ProtocolMessageHandlerBearer,
Serializable {
/**
* content type
*/
protected ProtocolMessageType protocolMessageType;
/**
* describes if the messages are coming from the client or the server.
*/
protected ConnectionEnd messageIssuer;
/**
* List of preconfigured records for this protocol message
*/
protected List<Record> records;
/**
* Defines whether this message is necessarily required in the workflow.
*/
private boolean required = true;
/**
* Defines if the message should be sent during the workflow. Using this
* flag it is possible to omit a message is sent during the handshake while
* it is executed to initialize specific variables.
*/
private boolean goingToBeSent = true;
/**
* Defines if the message should not be parsed and only forwarded during the
* MitMworkflow.
*/
private boolean goingToBeParsed = true;
/**
* Defines if the message should be modified during a workflow execution
* with MitMworkflowExecutor
*/
private boolean goingToBeModified = false;
/**
* resulting message
*/
@ModifiableVariableProperty(type = ModifiableVariableProperty.Type.PLAIN_PROTOCOL_MESSAGE)
protected ModifiableByteArray completeResultingMessage;
@Override
public abstract ProtocolMessageHandler<? extends ProtocolMessage> getProtocolMessageHandler(TlsContext tlsContext);
public ProtocolMessageType getProtocolMessageType() {
return protocolMessageType;
}
public ConnectionEnd getMessageIssuer() {
return messageIssuer;
}
public void setMessageIssuer(ConnectionEnd messageIssuer) {
this.messageIssuer = messageIssuer;
}
@XmlElementWrapper
@XmlElements(value = { @XmlElement(type = Record.class, name = "Record"),
@XmlElement(type = DtlsRecord.class, name = "DtlsRecord") })
public List<Record> getRecords() {
return records;
}
public void setRecords(List<Record> records) {
this.records = records;
}
public void addRecord(Record record) {
if (this.records == null) {
this.records = new LinkedList<>();
}
this.records.add(record);
}
public boolean isRequired() {
return required;
}
public void setRequired(boolean required) {
this.required = required;
}
public boolean isGoingToBeSent() {
return goingToBeSent;
}
public void setGoingToBeSent(boolean goingToBeSent) {
this.goingToBeSent = goingToBeSent;
}
public boolean isGoingToBeParsed() {
return goingToBeParsed;
}
public void setGoingToBeParsed(boolean goingToBeParsed) {
this.goingToBeParsed = goingToBeParsed;
}
public boolean isGoingToBeModified() {
return goingToBeModified;
}
public void setGoingToBeModified(boolean goingToBeModified) {
this.goingToBeModified = goingToBeModified;
}
@Override
public List<ModifiableVariableHolder> getAllModifiableVariableHolders() {
List<ModifiableVariableHolder> holders = super.getAllModifiableVariableHolders();
if (records != null) {
for (Record r : records) {
holders.add(r);
}
}
return holders;
}
@Override
public Field getRandomModifiableVariableField() {
List<Field> fields = getAllModifiableVariableFields();
int randomField = RandomHelper.getRandom().nextInt(fields.size());
return fields.get(randomField);
}
public ModifiableByteArray getCompleteResultingMessage() {
return completeResultingMessage;
}
public void setCompleteResultingMessage(ModifiableByteArray completeResultingMessage) {
this.completeResultingMessage = completeResultingMessage;
}
public void setCompleteResultingMessage(byte[] completeResultingMessage) {
this.completeResultingMessage = ModifiableVariableFactory.safelySetValue(this.completeResultingMessage,
completeResultingMessage);
}
public abstract String toCompactString();
}