aiocoap
aiocoap copied to clipboard
DTLS error: code 20 in loop
https://github.com/chrysn/aiocoap/blob/c8a24dec61a7d2f09d7469af8a0a66abe128a3af/aiocoap/transports/tinydtls.py#L236
My host (tradfri gateway) returns an 'ALRT 20 invalidate peer' when I enter wrong credentials. But then I see these messages in the log, over and over again. (looks like an infinite loop)
Nov 13 00:16:40 ALRT 20 invalidate peer
2017-11-13 00:16:40 ERROR (MainThread) [coap] Fatal DTLS error: code 20
Nov 13 00:16:40 WARN received alert, peer has been invalidated
Error in close: -1
Nov 13 00:16:40 ALRT 20 invalidate peer
2017-11-13 00:16:40 ERROR (MainThread) [coap] Fatal DTLS error: code 20
Nov 13 00:16:40 WARN received alert, peer has been invalidated
Error in close: -1
There's also an asyncio.CancelledError being raised here: https://github.com/chrysn/aiocoap/blob/c8a24dec61a7d2f09d7469af8a0a66abe128a3af/aiocoap/transports/tinydtls.py#L164 (that's not visible in the logs because I added an except asyncio.CancelledError: raise`)
As you can see, I've been trying to debug it, but I really don't know if I the issue is with the host or with tinydtls... the only thing I know is that it's unwanted behavior. (the issue is not that it doesn't accept the credentials, I'm entering them wrong on purpose to test the behavior on user error.)
My host (tradfri gateway) returns an 'ALRT 20 invalidate peer' when I enter wrong credentials. But then I see these messages in the log, over and over again. (looks like an infinite loop)
How many times is "over and over" ? If you tell me 7, it could be the retransmission of the last DTLS record taking place (default with tinydtls is 7).
Lets say 10 times a second for at least a minute or two. (probably until 'Request timed out' in protocol.py)
I don't have enough hardware for testing this specific behavior, but there are two ideas coming to my head:
1- The client is not aware of the invalidate state and it's believing the DTLS channel is ready, and therefore sending the CoAP messages (it's possible to send DTLS record app. data before the dtls session is completed. If this is the case, it can be verified with Wireshark (looking for DTLS Data application records that should be matching with the error message).
2- tinydtls-cython could be trying to validate packets already received, but I don't think so.
Of course, the part with the OSError
is another subject.
My knowledge is not great enough to properly debug it.
But it on this FATAL error/event it calls self._cancelled()
which does:
self._task.cancel()
self._task = asyncio.ensure_future(self._run(connect_immediately=False))
I noticed that in the meantime CoAP is still retransmitting (protocol.py line 333), because it never received an error through its _dispatch_error
function.
should new_error_callback
not be called instead of running it again which causes everything to start from the beginning again? (connects to host, that calls back to _event with that fatal DTLS error)
To be honest I haven't considered the code path for authentication failure yet.
I have so far not managed to reproduce the issue with my own Trådfri gateway; when I use a wrong key, the server did not send anything back after the "Server Hello Done" step.
Could you maybe set the wrong key to something you can give away, record a network log of the failure situation using wireshark or similar, and post it here?
(And yes, I know that the cancellation handling in the DTLS code so far is abysmal).
Attach is the traffic (Wireshark capture) with the tradfri gateway upon trying to connect with the wrong Security Code (from the back of the gateway)
I'm using the API from pytradfri by the way: https://github.com/ggravlingen/pytradfri/blob/master/pytradfri/api/aiocoap_api.py
My code (simplified a bit) looks like this:
api_factory = APIFactory("192.168.1.32", psk_id='some_random_identity_XXX')
psk = yield from api_factory.generate_psk("a_wrongly_entered_security_code")