diff --git a/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/message/AlertMessage.java b/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/message/AlertMessage.java index acc92e3742..2a347d20ee 100644 --- a/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/message/AlertMessage.java +++ b/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/message/AlertMessage.java @@ -114,11 +114,23 @@ public String toCompactString() { StringBuilder sb = new StringBuilder(); String levelString; String descriptionString; + + // Determine level string if (level != null && level.getValue() != null) { levelString = AlertLevel.getAlertLevel(level.getValue()).name(); + } else if (config != null && config.length == 2) { + // Use config as fallback for level + AlertLevel alertLevel = AlertLevel.getAlertLevel((byte) config[0]); + if (alertLevel != null) { + levelString = alertLevel.name(); + } else { + levelString = "" + config[0]; + } } else { - levelString = "null"; + levelString = "not configured"; } + + // Determine description string if (description != null && description.getValue() != null) { AlertDescription desc = AlertDescription.getAlertDescription(description.getValue()); if (desc != null) { @@ -126,18 +138,18 @@ public String toCompactString() { } else { descriptionString = "" + description.getValue(); } - } else { - if (config != null && config.length == 2) { - AlertDescription desc = AlertDescription.getAlertDescription((byte) config[1]); - if (desc != null) { - descriptionString = desc.name(); - } else { - descriptionString = "" + config[1]; - } + } else if (config != null && config.length == 2) { + // Use config as fallback for description + AlertDescription desc = AlertDescription.getAlertDescription((byte) config[1]); + if (desc != null) { + descriptionString = desc.name(); } else { - descriptionString = "null"; + descriptionString = "" + config[1]; } + } else { + descriptionString = "not configured"; } + sb.append("Alert(").append(levelString).append(",").append(descriptionString).append(")"); return sb.toString(); } diff --git a/TLS-Core/src/test/java/de/rub/nds/tlsattacker/core/protocol/message/AlertMessageToCompactStringTest.java b/TLS-Core/src/test/java/de/rub/nds/tlsattacker/core/protocol/message/AlertMessageToCompactStringTest.java new file mode 100644 index 0000000000..c41a01797d --- /dev/null +++ b/TLS-Core/src/test/java/de/rub/nds/tlsattacker/core/protocol/message/AlertMessageToCompactStringTest.java @@ -0,0 +1,84 @@ +/* + * TLS-Attacker - A Modular Penetration Testing Framework for TLS + * + * Copyright 2014-2023 Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License, Version 2.0 + * http://www.apache.org/licenses/LICENSE-2.0.txt + */ +package de.rub.nds.tlsattacker.core.protocol.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import de.rub.nds.tlsattacker.core.constants.AlertDescription; +import de.rub.nds.tlsattacker.core.constants.AlertLevel; +import org.junit.jupiter.api.Test; + +public class AlertMessageToCompactStringTest { + + @Test + public void testToCompactStringWithNullValues() { + AlertMessage message = new AlertMessage(); + // Both level and description are null, no config set + assertEquals("Alert(not configured,not configured)", message.toCompactString()); + } + + @Test + public void testToCompactStringWithConfig() { + AlertMessage message = new AlertMessage(); + // Set config with WARNING level (1) and BAD_RECORD_MAC description (20) + message.setConfig(new byte[] {1, 20}); + assertEquals("Alert(WARNING,BAD_RECORD_MAC)", message.toCompactString()); + } + + @Test + public void testToCompactStringWithExplicitValues() { + AlertMessage message = new AlertMessage(); + message.setLevel(AlertLevel.FATAL.getValue()); + message.setDescription(AlertDescription.HANDSHAKE_FAILURE.getValue()); + assertEquals("Alert(FATAL,HANDSHAKE_FAILURE)", message.toCompactString()); + } + + @Test + public void testToCompactStringWithUnknownValues() { + AlertMessage message = new AlertMessage(); + // Use values that don't correspond to known alert types + message.setConfig(new byte[] {99, 99}); + assertEquals("Alert(UNDEFINED,99)", message.toCompactString()); + } + + @Test + public void testToCompactStringWithPartialConfig() { + AlertMessage message = new AlertMessage(); + // Config with only one byte - should fall back to "not configured" + message.setConfig(new byte[] {1}); + assertEquals("Alert(not configured,not configured)", message.toCompactString()); + } + + @Test + public void testToCompactStringWithLevelButNoDescription() { + AlertMessage message = new AlertMessage(); + message.setLevel(AlertLevel.WARNING.getValue()); + // Description is null, no config + assertEquals("Alert(WARNING,not configured)", message.toCompactString()); + } + + @Test + public void testToCompactStringWithDescriptionButNoLevel() { + AlertMessage message = new AlertMessage(); + message.setDescription(AlertDescription.CLOSE_NOTIFY.getValue()); + // Level is null, no config + assertEquals("Alert(not configured,CLOSE_NOTIFY)", message.toCompactString()); + } + + @Test + public void testToCompactStringPrefersExplicitValuesOverConfig() { + AlertMessage message = new AlertMessage(); + // Set config + message.setConfig(new byte[] {1, 20}); + // But also set explicit values - these should take precedence + message.setLevel(AlertLevel.FATAL.getValue()); + message.setDescription(AlertDescription.UNEXPECTED_MESSAGE.getValue()); + assertEquals("Alert(FATAL,UNEXPECTED_MESSAGE)", message.toCompactString()); + } +}