Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to receive only one protocol message? #178

Open
GSoJC234 opened this issue Oct 17, 2024 · 7 comments
Open

How to receive only one protocol message? #178

GSoJC234 opened this issue Oct 17, 2024 · 7 comments
Labels

Comments

@GSoJC234
Copy link

GSoJC234 commented Oct 17, 2024

Hello,

I'm looking to implement a custom action that reads only any single protocol message.
I came across your comments on issue #177 and I believe the action for receiving just one protocol message might involve working with LayerConfiguration. (Is that correct?)

However, I'm having trouble deeply understanding how LayerConfiguration and LayerStack work.
Could you provide an example or sample code that demonstrates how to receive just any single protocol message?

Thank you for providing such a great TLS library!

Thank you!

@ic0ns
Copy link
Contributor

ic0ns commented Oct 17, 2024

For this you can take a look at the TightReceiveAction:

https://github.com/tls-attacker/TLS-Attacker/blob/main/TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/workflow/action/TightReceiveAction.java

A layer configuration is your encoding on how TLS-Attacker should behave on a given layer, i.e. which containers it should receive or which containers it should send. To limit the receiving of only the specified messages, you can use a TightReceiveLayerConfiguration, which is just a regular receiveConfiguration that sets "isProcessTrailingContainers" to false to tell the layer that once all messages are there no further messages should be processed.

@GSoJC234
Copy link
Author

GSoJC234 commented Oct 17, 2024

Thanks for your quick response!!

From what I understand,
TightReceiveAction takes expected messages as arguments and stops receiving once those expected messages are received.

However, in my case, the expected message isn't known in advance.
It can be a ClientHello, ServerHello, ServerKeyExchange, or any other protocol message.

Is there still a way to receive just a single protocol message using TightReceiveAction in this situation or is there any alternative way?

@ic0ns
Copy link
Contributor

ic0ns commented Oct 17, 2024

Ok this we did not have before. To realize this you need to write a custom layer configuration. I would simply extend the TightReceiveLayerConfiguration class and overwrite the function

executedAsPlanned(List<Container> list)

The function basically tells the layer when you are successful in the execution. In your case, if you overwrite it with:

return list.size() == 1;

the layer should then stop receiving once the first message is received.

@GSoJC234
Copy link
Author

Great!
Thank you for quick and detailed comments!

@GSoJC234
Copy link
Author

Hello,

I defined the custom layer TightReceiveOneLayerConfiguration, along with a ReceiveOneAction to receive only one valid handshake messages.

However, I encountered an issue with the receiveData method in LayerStack.java, which is responsible for receiving data

...
for (int i = 0; i < getLayerList().size(); i++) {
    ProtocolLayer layer = getLayerList().get(i);
    layer.clear();
    layer.setLayerConfiguration(layerConfigurationList.get(i));
}
...

The receiveData method always clear each layer including the Message Layer, Record Layer and TCP Layer, which are default layers used in TLS handshake process.

While it is okay to receive TCP packets corresponding a single TLS handshake message, the problem arises when I try to execute a sequence of actions like the following, in cases where the server sends multiple messages at once:

trace.addTlsAction(new ReceiveOneAction());  // Receive ServerHello
...
trace.addTlsAction(new ReceiveOneAction());  // Receive Certificate
...
trace.addTlsAction(new ReceiveOneAction());  // Receive ServerKeyExchange
...
trace.addTlsAction(new ReceiveOneAction());  // Receive ServerHelloDone
...

After the first action executed (receiving the ServerHello message), the remaining TCP packet data (stored in currentInputStream) gets discarded due to the layer.clear(). As a result, the subsequent ReceiveOneAction actions fail to receive the remaining messages.

To resolve this, I modified the receiveData method to avoid discarding currentInputStream when there is available data:

for (int i = 0; i < getLayerList().size(); i++) {
        ProtocolLayer layer = getLayerList().get(i);
        try {
            if (layer.currentInputStream == null || layer.currentInputStream.available() == 0) {
                layer.clear();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        layer.setLayerConfiguration(layerConfigurationList.get(i));
    }

Maybe TLS-Attacker's design intends to prevent parsing or processing only one valid message from a stream of received packets. I believe allowing this could be useful.

What do you think about enabling the option to receive only one valid message from a batch of received packets?

@GSoJC234 GSoJC234 reopened this Oct 20, 2024
@ic0ns
Copy link
Contributor

ic0ns commented Oct 21, 2024

Thats a good analysis. I think the mentioned behavior also kind of prevents the tight receive action from behaving as intended. I think your patch is not enough as the second action would now receive both more containers as expected since the produced data containers did not get reset - but the general idea seems right

@GSoJC234
Copy link
Author

I agree with your thoughts and suggestions!
Thank you for taking the time to review my issue.

@ic0ns ic0ns reopened this Oct 22, 2024
@ic0ns ic0ns added the bug label Oct 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants